libsmb: Remove sync cli_posix_readlink() wrapper
[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 #include "source3/lib/substitute.h"
55
56 #include <gnutls/gnutls.h>
57 #include <gnutls/crypto.h>
58
59 extern char *optarg;
60 extern int optind;
61
62 fstring host, workgroup, share, password, username, myname;
63 struct cli_credentials *torture_creds;
64 static const char *sockops="TCP_NODELAY";
65 int torture_nprocs=1;
66 static int port_to_use=0;
67 int torture_numops=100;
68 int torture_blocksize=1024*1024;
69 static int procnum; /* records process count number when forking */
70 static struct cli_state *current_cli;
71 static fstring randomfname;
72 static bool use_oplocks;
73 static bool use_level_II_oplocks;
74 static const char *client_txt = "client_oplocks.txt";
75 static bool disable_spnego;
76 static bool use_kerberos;
77 static bool force_dos_errors;
78 static fstring multishare_conn_fname;
79 static bool use_multishare_conn = False;
80 static bool do_encrypt;
81 static const char *local_path = NULL;
82 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
83 char *test_filename;
84
85 bool torture_showall = False;
86
87 static double create_procs(bool (*fn)(int), bool *result);
88
89 /********************************************************************
90  Ensure a connection is encrypted.
91 ********************************************************************/
92
93 static bool force_cli_encryption(struct cli_state *c,
94                         const char *sharename)
95 {
96         uint16_t major, minor;
97         uint32_t caplow, caphigh;
98         NTSTATUS status;
99
100         if (!SERVER_HAS_UNIX_CIFS(c)) {
101                 d_printf("Encryption required and "
102                         "server that doesn't support "
103                         "UNIX extensions - failing connect\n");
104                         return false;
105         }
106
107         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
108                                              &caphigh);
109         if (!NT_STATUS_IS_OK(status)) {
110                 d_printf("Encryption required and "
111                         "can't get UNIX CIFS extensions "
112                         "version from server: %s\n", nt_errstr(status));
113                 return false;
114         }
115
116         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
117                 d_printf("Encryption required and "
118                         "share %s doesn't support "
119                         "encryption.\n", sharename);
120                 return false;
121         }
122
123         status = cli_smb1_setup_encryption(c, torture_creds);
124         if (!NT_STATUS_IS_OK(status)) {
125                 d_printf("Encryption required and "
126                         "setup failed with error %s.\n",
127                         nt_errstr(status));
128                 return false;
129         }
130
131         return true;
132 }
133
134
135 static struct cli_state *open_nbt_connection(void)
136 {
137         struct cli_state *c;
138         NTSTATUS status;
139         int flags = 0;
140
141         if (disable_spnego) {
142                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
143         }
144
145         if (use_oplocks) {
146                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
147         }
148
149         if (use_level_II_oplocks) {
150                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
151         }
152
153         if (force_dos_errors) {
154                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
155         }
156
157         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
158                                 signing_state, flags, &c);
159         if (!NT_STATUS_IS_OK(status)) {
160                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
161                 return NULL;
162         }
163
164         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
165
166         return c;
167 }
168
169 /****************************************************************************
170  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 ****************************************************************************/
172
173 static bool cli_bad_session_request(int fd,
174                          struct nmb_name *calling, struct nmb_name *called)
175 {
176         TALLOC_CTX *frame;
177         uint8_t len_buf[4];
178         struct iovec iov[3];
179         ssize_t len;
180         uint8_t *inbuf;
181         int err;
182         bool ret = false;
183         uint8_t message_type;
184         uint8_t error;
185         struct tevent_context *ev;
186         struct tevent_req *req;
187
188         frame = talloc_stackframe();
189
190         iov[0].iov_base = len_buf;
191         iov[0].iov_len  = sizeof(len_buf);
192
193         /* put in the destination name */
194
195         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
196                                       called->name_type);
197         if (iov[1].iov_base == NULL) {
198                 goto fail;
199         }
200         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
201                                   talloc_get_size(iov[1].iov_base));
202
203         /* and my name */
204
205         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
206                                       calling->name_type);
207         if (iov[2].iov_base == NULL) {
208                 goto fail;
209         }
210         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
211                                   talloc_get_size(iov[2].iov_base));
212
213         /* Deliberately corrupt the name len (first byte) */
214         *((uint8_t *)iov[2].iov_base) = 100;
215
216         /* send a session request (RFC 1002) */
217         /* setup the packet length
218          * Remove four bytes from the length count, since the length
219          * field in the NBT Session Service header counts the number
220          * of bytes which follow.  The cli_send_smb() function knows
221          * about this and accounts for those four bytes.
222          * CRH.
223          */
224
225         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
226         SCVAL(len_buf,0,0x81);
227
228         len = write_data_iov(fd, iov, 3);
229         if (len == -1) {
230                 goto fail;
231         }
232
233         ev = samba_tevent_context_init(frame);
234         if (ev == NULL) {
235                 goto fail;
236         }
237         req = read_smb_send(frame, ev, fd);
238         if (req == NULL) {
239                 goto fail;
240         }
241         if (!tevent_req_poll(req, ev)) {
242                 goto fail;
243         }
244         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
245         if (len == -1) {
246                 errno = err;
247                 goto fail;
248         }
249         TALLOC_FREE(ev);
250
251         message_type = CVAL(inbuf, 0);
252         if (message_type != 0x83) {
253                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
254                           message_type);
255                 goto fail;
256         }
257
258         if (smb_len(inbuf) != 1) {
259                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
260                           (int)smb_len(inbuf));
261                 goto fail;
262         }
263
264         error = CVAL(inbuf, 4);
265         if (error !=  0x82) {
266                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
267                           (int)error);
268                 goto fail;
269         }
270
271         ret = true;
272 fail:
273         TALLOC_FREE(frame);
274         return ret;
275 }
276
277 /* Insert a NULL at the first separator of the given path and return a pointer
278  * to the remainder of the string.
279  */
280 static char *
281 terminate_path_at_separator(char * path)
282 {
283         char * p;
284
285         if (!path) {
286                 return NULL;
287         }
288
289         if ((p = strchr_m(path, '/'))) {
290                 *p = '\0';
291                 return p + 1;
292         }
293
294         if ((p = strchr_m(path, '\\'))) {
295                 *p = '\0';
296                 return p + 1;
297         }
298
299         /* No separator. */
300         return NULL;
301 }
302
303 /*
304   parse a //server/share type UNC name
305 */
306 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
307                       char **hostname, char **sharename)
308 {
309         char *p;
310
311         *hostname = *sharename = NULL;
312
313         if (strncmp(unc_name, "\\\\", 2) &&
314             strncmp(unc_name, "//", 2)) {
315                 return False;
316         }
317
318         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
319         p = terminate_path_at_separator(*hostname);
320
321         if (p && *p) {
322                 *sharename = talloc_strdup(mem_ctx, p);
323                 terminate_path_at_separator(*sharename);
324         }
325
326         if (*hostname && *sharename) {
327                 return True;
328         }
329
330         TALLOC_FREE(*hostname);
331         TALLOC_FREE(*sharename);
332         return False;
333 }
334
335 static bool torture_open_connection_share(struct cli_state **c,
336                                    const char *hostname, 
337                                    const char *sharename,
338                                    int flags)
339 {
340         NTSTATUS status;
341
342         status = cli_full_connection_creds(c,
343                                            myname,
344                                            hostname,
345                                            NULL, /* dest_ss */
346                                            port_to_use,
347                                            sharename,
348                                            "?????",
349                                            torture_creds,
350                                            flags);
351         if (!NT_STATUS_IS_OK(status)) {
352                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
353                         hostname, sharename, port_to_use, nt_errstr(status));
354                 return False;
355         }
356
357         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
358
359         if (do_encrypt) {
360                 return force_cli_encryption(*c,
361                                         sharename);
362         }
363         return True;
364 }
365
366 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
367 {
368         char **unc_list = NULL;
369         int num_unc_names = 0;
370         bool result;
371
372         if (use_multishare_conn==True) {
373                 char *h, *s;
374                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
375                 if (!unc_list || num_unc_names <= 0) {
376                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
377                         exit(1);
378                 }
379
380                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
381                                       NULL, &h, &s)) {
382                         printf("Failed to parse UNC name %s\n",
383                                unc_list[conn_index % num_unc_names]);
384                         TALLOC_FREE(unc_list);
385                         exit(1);
386                 }
387
388                 result = torture_open_connection_share(c, h, s, flags);
389
390                 /* h, s were copied earlier */
391                 TALLOC_FREE(unc_list);
392                 return result;
393         }
394
395         return torture_open_connection_share(c, host, share, flags);
396 }
397
398 bool torture_open_connection(struct cli_state **c, int conn_index)
399 {
400         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
401
402         if (use_oplocks) {
403                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
404         }
405         if (use_level_II_oplocks) {
406                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
407         }
408
409         return torture_open_connection_flags(c, conn_index, flags);
410 }
411
412 bool torture_init_connection(struct cli_state **pcli)
413 {
414         struct cli_state *cli;
415
416         cli = open_nbt_connection();
417         if (cli == NULL) {
418                 return false;
419         }
420
421         *pcli = cli;
422         return true;
423 }
424
425 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
426 {
427         uint16_t old_vuid = cli_state_get_uid(cli);
428         NTSTATUS status;
429         bool ret;
430
431         cli_state_set_uid(cli, 0);
432         status = cli_session_setup_creds(cli, torture_creds);
433         ret = NT_STATUS_IS_OK(status);
434         *new_vuid = cli_state_get_uid(cli);
435         cli_state_set_uid(cli, old_vuid);
436         return ret;
437 }
438
439
440 bool torture_close_connection(struct cli_state *c)
441 {
442         bool ret = True;
443         NTSTATUS status;
444
445         status = cli_tdis(c);
446         if (!NT_STATUS_IS_OK(status)) {
447                 printf("tdis failed (%s)\n", nt_errstr(status));
448                 ret = False;
449         }
450
451         cli_shutdown(c);
452
453         return ret;
454 }
455
456 void torture_conn_set_sockopt(struct cli_state *cli)
457 {
458         smbXcli_conn_set_sockopt(cli->conn, sockops);
459 }
460
461 static NTSTATUS torture_delete_fn(struct file_info *finfo,
462                                   const char *pattern,
463                                   void *state)
464 {
465         NTSTATUS status;
466         char *filename = NULL;
467         char *dirname = NULL;
468         char *p = NULL;
469         TALLOC_CTX *frame = talloc_stackframe();
470         struct cli_state *cli = (struct cli_state *)state;
471
472         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
473                 TALLOC_FREE(frame);
474                 return NT_STATUS_OK;
475         }
476
477         dirname = talloc_strdup(frame, pattern);
478         if (dirname == NULL) {
479                 TALLOC_FREE(frame);
480                 return NT_STATUS_NO_MEMORY;
481         }
482         p = strrchr_m(dirname, '\\');
483         if (p != NULL) {
484                 /* Remove the terminating '\' */
485                 *p = '\0';
486         }
487         if (dirname[0] != '\0') {
488                 filename = talloc_asprintf(frame,
489                                            "%s\\%s",
490                                            dirname,
491                                            finfo->name);
492         } else {
493                 filename = talloc_asprintf(frame,
494                                            "%s",
495                                            finfo->name);
496         }
497         if (filename == NULL) {
498                 TALLOC_FREE(frame);
499                 return NT_STATUS_NO_MEMORY;
500         }
501         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
502                 char *subdirname = talloc_asprintf(frame,
503                                                    "%s\\*",
504                                                    filename);
505                 if (subdirname == NULL) {
506                         TALLOC_FREE(frame);
507                         return NT_STATUS_NO_MEMORY;
508                 }
509                 status = cli_list(cli,
510                                   subdirname,
511                                   FILE_ATTRIBUTE_DIRECTORY |
512                                           FILE_ATTRIBUTE_HIDDEN |
513                                           FILE_ATTRIBUTE_SYSTEM,
514                                   torture_delete_fn,
515                                   cli);
516                 if (!NT_STATUS_IS_OK(status)) {
517                         printf("torture_delete_fn: cli_list "
518                                 "of %s failed (%s)\n",
519                                 subdirname,
520                                 nt_errstr(status));
521                         TALLOC_FREE(frame);
522                         return status;
523                 }
524                 status = cli_rmdir(cli, filename);
525         } else {
526                 status = cli_unlink(cli,
527                                     filename,
528                                     FILE_ATTRIBUTE_SYSTEM |
529                                         FILE_ATTRIBUTE_HIDDEN);
530         }
531         if (!NT_STATUS_IS_OK(status)) {
532                 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
533                         printf("torture_delete_fn: cli_rmdir"
534                                 " of %s failed (%s)\n",
535                                 filename,
536                                 nt_errstr(status));
537                 } else {
538                         printf("torture_delete_fn: cli_unlink"
539                                 " of %s failed (%s)\n",
540                                 filename,
541                                 nt_errstr(status));
542                 }
543         }
544         TALLOC_FREE(frame);
545         return status;
546 }
547
548 void torture_deltree(struct cli_state *cli, const char *dname)
549 {
550         char *mask = NULL;
551         NTSTATUS status;
552
553         /* It might be a file */
554         (void)cli_unlink(cli,
555                          dname,
556                          FILE_ATTRIBUTE_SYSTEM |
557                                 FILE_ATTRIBUTE_HIDDEN);
558
559         mask = talloc_asprintf(cli,
560                                "%s\\*",
561                                dname);
562         if (mask == NULL) {
563                 printf("torture_deltree: talloc_asprintf failed\n");
564                 return;
565         }
566
567         status = cli_list(cli,
568                         mask,
569                         FILE_ATTRIBUTE_DIRECTORY |
570                                 FILE_ATTRIBUTE_HIDDEN|
571                                 FILE_ATTRIBUTE_SYSTEM,
572                         torture_delete_fn,
573                         cli);
574         if (!NT_STATUS_IS_OK(status)) {
575                 printf("torture_deltree: cli_list of %s failed (%s)\n",
576                         mask,
577                         nt_errstr(status));
578         }
579         TALLOC_FREE(mask);
580         status = cli_rmdir(cli, dname);
581         if (!NT_STATUS_IS_OK(status)) {
582                 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
583                         dname,
584                         nt_errstr(status));
585         }
586 }
587
588 /* check if the server produced the expected dos or nt error code */
589 static bool check_both_error(int line, NTSTATUS status,
590                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
591 {
592         if (NT_STATUS_IS_DOS(status)) {
593                 uint8_t cclass;
594                 uint32_t num;
595
596                 /* Check DOS error */
597                 cclass = NT_STATUS_DOS_CLASS(status);
598                 num = NT_STATUS_DOS_CODE(status);
599
600                 if (eclass != cclass || ecode != num) {
601                         printf("unexpected error code class=%d code=%d\n",
602                                (int)cclass, (int)num);
603                         printf(" expected %d/%d %s (line=%d)\n",
604                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
605                         return false;
606                 }
607         } else {
608                 /* Check NT error */
609                 if (!NT_STATUS_EQUAL(nterr, status)) {
610                         printf("unexpected error code %s\n",
611                                 nt_errstr(status));
612                         printf(" expected %s (line=%d)\n",
613                                 nt_errstr(nterr), line);
614                         return false;
615                 }
616         }
617
618         return true;
619 }
620
621
622 /* check if the server produced the expected error code */
623 static bool check_error(int line, NTSTATUS status,
624                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
625 {
626         if (NT_STATUS_IS_DOS(status)) {
627                 uint8_t cclass;
628                 uint32_t num;
629
630                 /* Check DOS error */
631
632                 cclass = NT_STATUS_DOS_CLASS(status);
633                 num = NT_STATUS_DOS_CODE(status);
634
635                 if (eclass != cclass || ecode != num) {
636                         printf("unexpected error code class=%d code=%d\n", 
637                                (int)cclass, (int)num);
638                         printf(" expected %d/%d %s (line=%d)\n", 
639                                (int)eclass, (int)ecode, nt_errstr(nterr),
640                                line);
641                         return False;
642                 }
643
644         } else {
645                 /* Check NT error */
646
647                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
648                         printf("unexpected error code %s\n",
649                                nt_errstr(status));
650                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
651                                line);
652                         return False;
653                 }
654         }
655
656         return True;
657 }
658
659
660 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
661 {
662         NTSTATUS status;
663
664         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
665
666         while (!NT_STATUS_IS_OK(status)) {
667                 if (!check_both_error(__LINE__, status, ERRDOS,
668                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
669                         return false;
670                 }
671
672                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
673         }
674
675         return true;
676 }
677
678
679 static bool rw_torture(struct cli_state *c)
680 {
681         const char *lockfname = "\\torture.lck";
682         fstring fname;
683         uint16_t fnum;
684         uint16_t fnum2;
685         pid_t pid2, pid = getpid();
686         int i, j;
687         char buf[1024];
688         bool correct = True;
689         size_t nread = 0;
690         NTSTATUS status;
691
692         memset(buf, '\0', sizeof(buf));
693
694         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
695                          DENY_NONE, &fnum2);
696         if (!NT_STATUS_IS_OK(status)) {
697                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
698         }
699         if (!NT_STATUS_IS_OK(status)) {
700                 printf("open of %s failed (%s)\n",
701                        lockfname, nt_errstr(status));
702                 return False;
703         }
704
705         for (i=0;i<torture_numops;i++) {
706                 unsigned n = (unsigned)sys_random()%10;
707
708                 if (i % 10 == 0) {
709                         printf("%d\r", i); fflush(stdout);
710                 }
711                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
712
713                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
714                         return False;
715                 }
716
717                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
718                                   DENY_ALL, &fnum);
719                 if (!NT_STATUS_IS_OK(status)) {
720                         printf("open failed (%s)\n", nt_errstr(status));
721                         correct = False;
722                         break;
723                 }
724
725                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
726                                       sizeof(pid), NULL);
727                 if (!NT_STATUS_IS_OK(status)) {
728                         printf("write failed (%s)\n", nt_errstr(status));
729                         correct = False;
730                 }
731
732                 for (j=0;j<50;j++) {
733                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
734                                               sizeof(pid)+(j*sizeof(buf)),
735                                               sizeof(buf), NULL);
736                         if (!NT_STATUS_IS_OK(status)) {
737                                 printf("write failed (%s)\n",
738                                        nt_errstr(status));
739                                 correct = False;
740                         }
741                 }
742
743                 pid2 = 0;
744
745                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
746                                   &nread);
747                 if (!NT_STATUS_IS_OK(status)) {
748                         printf("read failed (%s)\n", nt_errstr(status));
749                         correct = false;
750                 } else if (nread != sizeof(pid)) {
751                         printf("read/write compare failed: "
752                                "recv %ld req %ld\n", (unsigned long)nread,
753                                (unsigned long)sizeof(pid));
754                         correct = false;
755                 }
756
757                 if (pid2 != pid) {
758                         printf("data corruption!\n");
759                         correct = False;
760                 }
761
762                 status = cli_close(c, fnum);
763                 if (!NT_STATUS_IS_OK(status)) {
764                         printf("close failed (%s)\n", nt_errstr(status));
765                         correct = False;
766                 }
767
768                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
769                 if (!NT_STATUS_IS_OK(status)) {
770                         printf("unlink failed (%s)\n", nt_errstr(status));
771                         correct = False;
772                 }
773
774                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
775                 if (!NT_STATUS_IS_OK(status)) {
776                         printf("unlock failed (%s)\n", nt_errstr(status));
777                         correct = False;
778                 }
779         }
780
781         cli_close(c, fnum2);
782         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
783
784         printf("%d\n", i);
785
786         return correct;
787 }
788
789 static bool run_torture(int dummy)
790 {
791         struct cli_state *cli;
792         bool ret;
793
794         cli = current_cli;
795
796         smbXcli_conn_set_sockopt(cli->conn, sockops);
797
798         ret = rw_torture(cli);
799
800         if (!torture_close_connection(cli)) {
801                 ret = False;
802         }
803
804         return ret;
805 }
806
807 static bool rw_torture3(struct cli_state *c, char *lockfname)
808 {
809         uint16_t fnum = (uint16_t)-1;
810         unsigned int i = 0;
811         char buf[131072];
812         char buf_rd[131072];
813         unsigned count;
814         unsigned countprev = 0;
815         size_t sent = 0;
816         bool correct = True;
817         NTSTATUS status = NT_STATUS_OK;
818
819         srandom(1);
820         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
821         {
822                 SIVAL(buf, i, sys_random());
823         }
824
825         if (procnum == 0)
826         {
827                 status = cli_unlink(
828                         c, lockfname,
829                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830                 if (!NT_STATUS_IS_OK(status)) {
831                         printf("unlink failed (%s) (normal, this file should "
832                                "not exist)\n", nt_errstr(status));
833                 }
834
835                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
836                                   DENY_NONE, &fnum);
837                 if (!NT_STATUS_IS_OK(status)) {
838                         printf("first open read/write of %s failed (%s)\n",
839                                         lockfname, nt_errstr(status));
840                         return False;
841                 }
842         }
843         else
844         {
845                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
846                 {
847                         status = cli_openx(c, lockfname, O_RDONLY, 
848                                          DENY_NONE, &fnum);
849                         if (NT_STATUS_IS_OK(status)) {
850                                 break;
851                         }
852                         smb_msleep(10);
853                 }
854                 if (!NT_STATUS_IS_OK(status)) {
855                         printf("second open read-only of %s failed (%s)\n",
856                                         lockfname, nt_errstr(status));
857                         return False;
858                 }
859         }
860
861         i = 0;
862         for (count = 0; count < sizeof(buf); count += sent)
863         {
864                 if (count >= countprev) {
865                         printf("%d %8d\r", i, count);
866                         fflush(stdout);
867                         i++;
868                         countprev += (sizeof(buf) / 20);
869                 }
870
871                 if (procnum == 0)
872                 {
873                         sent = ((unsigned)sys_random()%(20))+ 1;
874                         if (sent > sizeof(buf) - count)
875                         {
876                                 sent = sizeof(buf) - count;
877                         }
878
879                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
880                                               count, sent, NULL);
881                         if (!NT_STATUS_IS_OK(status)) {
882                                 printf("write failed (%s)\n",
883                                        nt_errstr(status));
884                                 correct = False;
885                         }
886                 }
887                 else
888                 {
889                         status = cli_read(c, fnum, buf_rd+count, count,
890                                           sizeof(buf)-count, &sent);
891                         if(!NT_STATUS_IS_OK(status)) {
892                                 printf("read failed offset:%d size:%ld (%s)\n",
893                                        count, (unsigned long)sizeof(buf)-count,
894                                        nt_errstr(status));
895                                 correct = False;
896                                 sent = 0;
897                         } else if (sent > 0) {
898                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
899                                 {
900                                         printf("read/write compare failed\n");
901                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
902                                         correct = False;
903                                         break;
904                                 }
905                         }
906                 }
907
908         }
909
910         status = cli_close(c, fnum);
911         if (!NT_STATUS_IS_OK(status)) {
912                 printf("close failed (%s)\n", nt_errstr(status));
913                 correct = False;
914         }
915
916         return correct;
917 }
918
919 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
920 {
921         const char *lockfname = "\\torture2.lck";
922         uint16_t fnum1;
923         uint16_t fnum2;
924         int i;
925         char buf[131072];
926         char buf_rd[131072];
927         bool correct = True;
928         size_t bytes_read;
929         NTSTATUS status;
930
931         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
932         if (!NT_STATUS_IS_OK(status)) {
933                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
934         }
935
936         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
937                           DENY_NONE, &fnum1);
938         if (!NT_STATUS_IS_OK(status)) {
939                 printf("first open read/write of %s failed (%s)\n",
940                                 lockfname, nt_errstr(status));
941                 return False;
942         }
943
944         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
945         if (!NT_STATUS_IS_OK(status)) {
946                 printf("second open read-only of %s failed (%s)\n",
947                                 lockfname, nt_errstr(status));
948                 cli_close(c1, fnum1);
949                 return False;
950         }
951
952         for (i = 0; i < torture_numops; i++)
953         {
954                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
955                 if (i % 10 == 0) {
956                         printf("%d\r", i); fflush(stdout);
957                 }
958
959                 generate_random_buffer((unsigned char *)buf, buf_size);
960
961                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
962                                       buf_size, NULL);
963                 if (!NT_STATUS_IS_OK(status)) {
964                         printf("write failed (%s)\n", nt_errstr(status));
965                         correct = False;
966                         break;
967                 }
968
969                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
970                 if(!NT_STATUS_IS_OK(status)) {
971                         printf("read failed (%s)\n", nt_errstr(status));
972                         correct = false;
973                         break;
974                 } else if (bytes_read != buf_size) {
975                         printf("read failed\n");
976                         printf("read %ld, expected %ld\n",
977                                (unsigned long)bytes_read,
978                                (unsigned long)buf_size); 
979                         correct = False;
980                         break;
981                 }
982
983                 if (memcmp(buf_rd, buf, buf_size) != 0)
984                 {
985                         printf("read/write compare failed\n");
986                         correct = False;
987                         break;
988                 }
989         }
990
991         status = cli_close(c2, fnum2);
992         if (!NT_STATUS_IS_OK(status)) {
993                 printf("close failed (%s)\n", nt_errstr(status));
994                 correct = False;
995         }
996
997         status = cli_close(c1, fnum1);
998         if (!NT_STATUS_IS_OK(status)) {
999                 printf("close failed (%s)\n", nt_errstr(status));
1000                 correct = False;
1001         }
1002
1003         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 printf("unlink failed (%s)\n", nt_errstr(status));
1006                 correct = False;
1007         }
1008
1009         return correct;
1010 }
1011
1012 static bool run_readwritetest(int dummy)
1013 {
1014         struct cli_state *cli1, *cli2;
1015         bool test1, test2 = False;
1016
1017         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1018                 return False;
1019         }
1020         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1021         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1022
1023         printf("starting readwritetest\n");
1024
1025         test1 = rw_torture2(cli1, cli2);
1026         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1027
1028         if (test1) {
1029                 test2 = rw_torture2(cli1, cli1);
1030                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1031         }
1032
1033         if (!torture_close_connection(cli1)) {
1034                 test1 = False;
1035         }
1036
1037         if (!torture_close_connection(cli2)) {
1038                 test2 = False;
1039         }
1040
1041         return (test1 && test2);
1042 }
1043
1044 static bool run_readwritemulti(int dummy)
1045 {
1046         struct cli_state *cli;
1047         bool test;
1048
1049         cli = current_cli;
1050
1051         smbXcli_conn_set_sockopt(cli->conn, sockops);
1052
1053         printf("run_readwritemulti: fname %s\n", randomfname);
1054         test = rw_torture3(cli, randomfname);
1055
1056         if (!torture_close_connection(cli)) {
1057                 test = False;
1058         }
1059
1060         return test;
1061 }
1062
1063 static bool run_readwritelarge_internal(void)
1064 {
1065         static struct cli_state *cli1;
1066         uint16_t fnum1;
1067         const char *lockfname = "\\large.dat";
1068         off_t fsize;
1069         char buf[126*1024];
1070         bool correct = True;
1071         NTSTATUS status;
1072
1073         if (!torture_open_connection(&cli1, 0)) {
1074                 return False;
1075         }
1076         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1077         memset(buf,'\0',sizeof(buf));
1078
1079         printf("starting readwritelarge_internal\n");
1080
1081         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1082
1083         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1084                           DENY_NONE, &fnum1);
1085         if (!NT_STATUS_IS_OK(status)) {
1086                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1087                 return False;
1088         }
1089
1090         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1091
1092         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1093                                      NULL, NULL, NULL);
1094         if (!NT_STATUS_IS_OK(status)) {
1095                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1096                 correct = False;
1097         }
1098
1099         if (fsize == sizeof(buf))
1100                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1101                        (unsigned long)fsize);
1102         else {
1103                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1104                        (unsigned long)fsize);
1105                 correct = False;
1106         }
1107
1108         status = cli_close(cli1, fnum1);
1109         if (!NT_STATUS_IS_OK(status)) {
1110                 printf("close failed (%s)\n", nt_errstr(status));
1111                 correct = False;
1112         }
1113
1114         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1115         if (!NT_STATUS_IS_OK(status)) {
1116                 printf("unlink failed (%s)\n", nt_errstr(status));
1117                 correct = False;
1118         }
1119
1120         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1121                           DENY_NONE, &fnum1);
1122         if (!NT_STATUS_IS_OK(status)) {
1123                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1124                 return False;
1125         }
1126
1127         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1128
1129         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1130                                      NULL, NULL, NULL);
1131         if (!NT_STATUS_IS_OK(status)) {
1132                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1133                 correct = False;
1134         }
1135
1136         if (fsize == sizeof(buf))
1137                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1138                        (unsigned long)fsize);
1139         else {
1140                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1141                        (unsigned long)fsize);
1142                 correct = False;
1143         }
1144
1145         status = cli_close(cli1, fnum1);
1146         if (!NT_STATUS_IS_OK(status)) {
1147                 printf("close failed (%s)\n", nt_errstr(status));
1148                 correct = False;
1149         }
1150
1151         if (!torture_close_connection(cli1)) {
1152                 correct = False;
1153         }
1154         return correct;
1155 }
1156
1157 static bool run_readwritelarge(int dummy)
1158 {
1159         return run_readwritelarge_internal();
1160 }
1161
1162 static bool run_readwritelarge_signtest(int dummy)
1163 {
1164         bool ret;
1165         signing_state = SMB_SIGNING_REQUIRED;
1166         ret = run_readwritelarge_internal();
1167         signing_state = SMB_SIGNING_DEFAULT;
1168         return ret;
1169 }
1170
1171 int line_count = 0;
1172 int nbio_id;
1173
1174 #define ival(s) strtol(s, NULL, 0)
1175
1176 /* run a test that simulates an approximate netbench client load */
1177 static bool run_netbench(int client)
1178 {
1179         struct cli_state *cli;
1180         int i;
1181         char line[1024];
1182         char cname[20];
1183         FILE *f;
1184         const char *params[20];
1185         bool correct = True;
1186
1187         cli = current_cli;
1188
1189         nbio_id = client;
1190
1191         smbXcli_conn_set_sockopt(cli->conn, sockops);
1192
1193         nb_setup(cli);
1194
1195         slprintf(cname,sizeof(cname)-1, "client%d", client);
1196
1197         f = fopen(client_txt, "r");
1198
1199         if (!f) {
1200                 perror(client_txt);
1201                 return False;
1202         }
1203
1204         while (fgets(line, sizeof(line)-1, f)) {
1205                 char *saveptr;
1206                 line_count++;
1207
1208                 line[strlen(line)-1] = 0;
1209
1210                 /* printf("[%d] %s\n", line_count, line); */
1211
1212                 all_string_sub(line,"client1", cname, sizeof(line));
1213
1214                 /* parse the command parameters */
1215                 params[0] = strtok_r(line, " ", &saveptr);
1216                 i = 0;
1217                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1218
1219                 params[i] = "";
1220
1221                 if (i < 2) continue;
1222
1223                 if (!strncmp(params[0],"SMB", 3)) {
1224                         printf("ERROR: You are using a dbench 1 load file\n");
1225                         exit(1);
1226                 }
1227
1228                 if (!strcmp(params[0],"NTCreateX")) {
1229                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1230                                    ival(params[4]));
1231                 } else if (!strcmp(params[0],"Close")) {
1232                         nb_close(ival(params[1]));
1233                 } else if (!strcmp(params[0],"Rename")) {
1234                         nb_rename(params[1], params[2]);
1235                 } else if (!strcmp(params[0],"Unlink")) {
1236                         nb_unlink(params[1]);
1237                 } else if (!strcmp(params[0],"Deltree")) {
1238                         nb_deltree(params[1]);
1239                 } else if (!strcmp(params[0],"Rmdir")) {
1240                         nb_rmdir(params[1]);
1241                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1242                         nb_qpathinfo(params[1]);
1243                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1244                         nb_qfileinfo(ival(params[1]));
1245                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1246                         nb_qfsinfo(ival(params[1]));
1247                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1248                         nb_findfirst(params[1]);
1249                 } else if (!strcmp(params[0],"WriteX")) {
1250                         nb_writex(ival(params[1]), 
1251                                   ival(params[2]), ival(params[3]), ival(params[4]));
1252                 } else if (!strcmp(params[0],"ReadX")) {
1253                         nb_readx(ival(params[1]), 
1254                                   ival(params[2]), ival(params[3]), ival(params[4]));
1255                 } else if (!strcmp(params[0],"Flush")) {
1256                         nb_flush(ival(params[1]));
1257                 } else {
1258                         printf("Unknown operation %s\n", params[0]);
1259                         exit(1);
1260                 }
1261         }
1262         fclose(f);
1263
1264         nb_cleanup();
1265
1266         if (!torture_close_connection(cli)) {
1267                 correct = False;
1268         }
1269
1270         return correct;
1271 }
1272
1273
1274 /* run a test that simulates an approximate netbench client load */
1275 static bool run_nbench(int dummy)
1276 {
1277         double t;
1278         bool correct = True;
1279
1280         nbio_shmem(torture_nprocs);
1281
1282         nbio_id = -1;
1283
1284         signal(SIGALRM, nb_alarm);
1285         alarm(1);
1286         t = create_procs(run_netbench, &correct);
1287         alarm(0);
1288
1289         printf("\nThroughput %g MB/sec\n", 
1290                1.0e-6 * nbio_total() / t);
1291         return correct;
1292 }
1293
1294
1295 /*
1296   This test checks for two things:
1297
1298   1) correct support for retaining locks over a close (ie. the server
1299      must not use posix semantics)
1300   2) support for lock timeouts
1301  */
1302 static bool run_locktest1(int dummy)
1303 {
1304         struct cli_state *cli1, *cli2;
1305         const char *fname = "\\lockt1.lck";
1306         uint16_t fnum1, fnum2, fnum3;
1307         time_t t1, t2;
1308         unsigned lock_timeout;
1309         NTSTATUS status;
1310
1311         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1312                 return False;
1313         }
1314         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1315         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1316
1317         printf("starting locktest1\n");
1318
1319         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1320
1321         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1322                           &fnum1);
1323         if (!NT_STATUS_IS_OK(status)) {
1324                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1325                 return False;
1326         }
1327
1328         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1329         if (!NT_STATUS_IS_OK(status)) {
1330                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1331                 return False;
1332         }
1333
1334         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1335         if (!NT_STATUS_IS_OK(status)) {
1336                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1337                 return False;
1338         }
1339
1340         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1341         if (!NT_STATUS_IS_OK(status)) {
1342                 printf("lock1 failed (%s)\n", nt_errstr(status));
1343                 return false;
1344         }
1345
1346         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1347         if (NT_STATUS_IS_OK(status)) {
1348                 printf("lock2 succeeded! This is a locking bug\n");
1349                 return false;
1350         } else {
1351                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1352                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1353                         return false;
1354                 }
1355         }
1356
1357         lock_timeout = (1 + (random() % 20));
1358         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1359         t1 = time(NULL);
1360         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1361         if (NT_STATUS_IS_OK(status)) {
1362                 printf("lock3 succeeded! This is a locking bug\n");
1363                 return false;
1364         } else {
1365                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1366                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1367                         return false;
1368                 }
1369         }
1370         t2 = time(NULL);
1371
1372         if (ABS(t2 - t1) < lock_timeout-1) {
1373                 printf("error: This server appears not to support timed lock requests\n");
1374         }
1375
1376         printf("server slept for %u seconds for a %u second timeout\n",
1377                (unsigned int)(t2-t1), lock_timeout);
1378
1379         status = cli_close(cli1, fnum2);
1380         if (!NT_STATUS_IS_OK(status)) {
1381                 printf("close1 failed (%s)\n", nt_errstr(status));
1382                 return False;
1383         }
1384
1385         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1386         if (NT_STATUS_IS_OK(status)) {
1387                 printf("lock4 succeeded! This is a locking bug\n");
1388                 return false;
1389         } else {
1390                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1391                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1392                         return false;
1393                 }
1394         }
1395
1396         status = cli_close(cli1, fnum1);
1397         if (!NT_STATUS_IS_OK(status)) {
1398                 printf("close2 failed (%s)\n", nt_errstr(status));
1399                 return False;
1400         }
1401
1402         status = cli_close(cli2, fnum3);
1403         if (!NT_STATUS_IS_OK(status)) {
1404                 printf("close3 failed (%s)\n", nt_errstr(status));
1405                 return False;
1406         }
1407
1408         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1409         if (!NT_STATUS_IS_OK(status)) {
1410                 printf("unlink failed (%s)\n", nt_errstr(status));
1411                 return False;
1412         }
1413
1414
1415         if (!torture_close_connection(cli1)) {
1416                 return False;
1417         }
1418
1419         if (!torture_close_connection(cli2)) {
1420                 return False;
1421         }
1422
1423         printf("Passed locktest1\n");
1424         return True;
1425 }
1426
1427 /*
1428   this checks to see if a secondary tconx can use open files from an
1429   earlier tconx
1430  */
1431 static bool run_tcon_test(int dummy)
1432 {
1433         static struct cli_state *cli;
1434         const char *fname = "\\tcontest.tmp";
1435         uint16_t fnum1;
1436         uint32_t cnum1, cnum2, cnum3;
1437         struct smbXcli_tcon *orig_tcon = NULL;
1438         char *orig_share = NULL;
1439         uint16_t vuid1, vuid2;
1440         char buf[4];
1441         bool ret = True;
1442         NTSTATUS status;
1443
1444         memset(buf, '\0', sizeof(buf));
1445
1446         if (!torture_open_connection(&cli, 0)) {
1447                 return False;
1448         }
1449         smbXcli_conn_set_sockopt(cli->conn, sockops);
1450
1451         printf("starting tcontest\n");
1452
1453         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1454
1455         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1456         if (!NT_STATUS_IS_OK(status)) {
1457                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1458                 return False;
1459         }
1460
1461         cnum1 = cli_state_get_tid(cli);
1462         vuid1 = cli_state_get_uid(cli);
1463
1464         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1465         if (!NT_STATUS_IS_OK(status)) {
1466                 printf("initial write failed (%s)", nt_errstr(status));
1467                 return False;
1468         }
1469
1470         cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1471
1472         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1473         if (!NT_STATUS_IS_OK(status)) {
1474                 printf("%s refused 2nd tree connect (%s)\n", host,
1475                        nt_errstr(status));
1476                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1477                 cli_shutdown(cli);
1478                 return False;
1479         }
1480
1481         cnum2 = cli_state_get_tid(cli);
1482         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1483         vuid2 = cli_state_get_uid(cli) + 1;
1484
1485         /* try a write with the wrong tid */
1486         cli_state_set_tid(cli, cnum2);
1487
1488         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1489         if (NT_STATUS_IS_OK(status)) {
1490                 printf("* server allows write with wrong TID\n");
1491                 ret = False;
1492         } else {
1493                 printf("server fails write with wrong TID : %s\n",
1494                        nt_errstr(status));
1495         }
1496
1497
1498         /* try a write with an invalid tid */
1499         cli_state_set_tid(cli, cnum3);
1500
1501         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1502         if (NT_STATUS_IS_OK(status)) {
1503                 printf("* server allows write with invalid TID\n");
1504                 ret = False;
1505         } else {
1506                 printf("server fails write with invalid TID : %s\n",
1507                        nt_errstr(status));
1508         }
1509
1510         /* try a write with an invalid vuid */
1511         cli_state_set_uid(cli, vuid2);
1512         cli_state_set_tid(cli, cnum1);
1513
1514         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1515         if (NT_STATUS_IS_OK(status)) {
1516                 printf("* server allows write with invalid VUID\n");
1517                 ret = False;
1518         } else {
1519                 printf("server fails write with invalid VUID : %s\n",
1520                        nt_errstr(status));
1521         }
1522
1523         cli_state_set_tid(cli, cnum1);
1524         cli_state_set_uid(cli, vuid1);
1525
1526         status = cli_close(cli, fnum1);
1527         if (!NT_STATUS_IS_OK(status)) {
1528                 printf("close failed (%s)\n", nt_errstr(status));
1529                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1530                 cli_shutdown(cli);
1531                 return False;
1532         }
1533
1534         cli_state_set_tid(cli, cnum2);
1535
1536         status = cli_tdis(cli);
1537         if (!NT_STATUS_IS_OK(status)) {
1538                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1539                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1540                 cli_shutdown(cli);
1541                 return False;
1542         }
1543
1544         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1545
1546         cli_state_set_tid(cli, cnum1);
1547
1548         if (!torture_close_connection(cli)) {
1549                 return False;
1550         }
1551
1552         return ret;
1553 }
1554
1555
1556 /*
1557  checks for old style tcon support
1558  */
1559 static bool run_tcon2_test(int dummy)
1560 {
1561         static struct cli_state *cli;
1562         uint16_t cnum, max_xmit;
1563         char *service;
1564         NTSTATUS status;
1565
1566         if (!torture_open_connection(&cli, 0)) {
1567                 return False;
1568         }
1569         smbXcli_conn_set_sockopt(cli->conn, sockops);
1570
1571         printf("starting tcon2 test\n");
1572
1573         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1574                 return false;
1575         }
1576
1577         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1578
1579         SAFE_FREE(service);
1580
1581         if (!NT_STATUS_IS_OK(status)) {
1582                 printf("tcon2 failed : %s\n", nt_errstr(status));
1583         } else {
1584                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1585                        (int)max_xmit, (int)cnum);
1586         }
1587
1588         if (!torture_close_connection(cli)) {
1589                 return False;
1590         }
1591
1592         printf("Passed tcon2 test\n");
1593         return True;
1594 }
1595
1596 static bool tcon_devtest(struct cli_state *cli,
1597                          const char *myshare, const char *devtype,
1598                          const char *return_devtype,
1599                          NTSTATUS expected_error)
1600 {
1601         NTSTATUS status;
1602         bool ret;
1603
1604         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1605
1606         if (NT_STATUS_IS_OK(expected_error)) {
1607                 if (NT_STATUS_IS_OK(status)) {
1608                         if (return_devtype != NULL &&
1609                             strequal(cli->dev, return_devtype)) {
1610                                 ret = True;
1611                         } else { 
1612                                 printf("tconX to share %s with type %s "
1613                                        "succeeded but returned the wrong "
1614                                        "device type (got [%s] but should have got [%s])\n",
1615                                        myshare, devtype, cli->dev, return_devtype);
1616                                 ret = False;
1617                         }
1618                 } else {
1619                         printf("tconX to share %s with type %s "
1620                                "should have succeeded but failed\n",
1621                                myshare, devtype);
1622                         ret = False;
1623                 }
1624                 cli_tdis(cli);
1625         } else {
1626                 if (NT_STATUS_IS_OK(status)) {
1627                         printf("tconx to share %s with type %s "
1628                                "should have failed but succeeded\n",
1629                                myshare, devtype);
1630                         ret = False;
1631                 } else {
1632                         if (NT_STATUS_EQUAL(status, expected_error)) {
1633                                 ret = True;
1634                         } else {
1635                                 printf("Returned unexpected error\n");
1636                                 ret = False;
1637                         }
1638                 }
1639         }
1640         return ret;
1641 }
1642
1643 /*
1644  checks for correct tconX support
1645  */
1646 static bool run_tcon_devtype_test(int dummy)
1647 {
1648         static struct cli_state *cli1 = NULL;
1649         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1650         NTSTATUS status;
1651         bool ret = True;
1652
1653         status = cli_full_connection_creds(&cli1,
1654                                            myname,
1655                                            host,
1656                                            NULL, /* dest_ss */
1657                                            port_to_use,
1658                                            NULL, /* service */
1659                                            NULL, /* service_type */
1660                                            torture_creds,
1661                                            flags);
1662
1663         if (!NT_STATUS_IS_OK(status)) {
1664                 printf("could not open connection\n");
1665                 return False;
1666         }
1667
1668         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1669                 ret = False;
1670
1671         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1672                 ret = False;
1673
1674         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1675                 ret = False;
1676
1677         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1678                 ret = False;
1679
1680         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1681                 ret = False;
1682
1683         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1684                 ret = False;
1685
1686         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1687                 ret = False;
1688
1689         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1690                 ret = False;
1691
1692         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1693                 ret = False;
1694
1695         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1696                 ret = False;
1697
1698         cli_shutdown(cli1);
1699
1700         if (ret)
1701                 printf("Passed tcondevtest\n");
1702
1703         return ret;
1704 }
1705
1706
1707 /*
1708   This test checks that 
1709
1710   1) the server supports multiple locking contexts on the one SMB
1711   connection, distinguished by PID.  
1712
1713   2) the server correctly fails overlapping locks made by the same PID (this
1714      goes against POSIX behaviour, which is why it is tricky to implement)
1715
1716   3) the server denies unlock requests by an incorrect client PID
1717 */
1718 static bool run_locktest2(int dummy)
1719 {
1720         static struct cli_state *cli;
1721         const char *fname = "\\lockt2.lck";
1722         uint16_t fnum1, fnum2, fnum3;
1723         bool correct = True;
1724         NTSTATUS status;
1725
1726         if (!torture_open_connection(&cli, 0)) {
1727                 return False;
1728         }
1729
1730         smbXcli_conn_set_sockopt(cli->conn, sockops);
1731
1732         printf("starting locktest2\n");
1733
1734         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1735
1736         cli_setpid(cli, 1);
1737
1738         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1739         if (!NT_STATUS_IS_OK(status)) {
1740                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1741                 return False;
1742         }
1743
1744         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1745         if (!NT_STATUS_IS_OK(status)) {
1746                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1747                 return False;
1748         }
1749
1750         cli_setpid(cli, 2);
1751
1752         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1753         if (!NT_STATUS_IS_OK(status)) {
1754                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1755                 return False;
1756         }
1757
1758         cli_setpid(cli, 1);
1759
1760         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1761         if (!NT_STATUS_IS_OK(status)) {
1762                 printf("lock1 failed (%s)\n", nt_errstr(status));
1763                 return false;
1764         }
1765
1766         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1767         if (NT_STATUS_IS_OK(status)) {
1768                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1769                 correct = false;
1770         } else {
1771                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1772                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1773                         return false;
1774                 }
1775         }
1776
1777         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1778         if (NT_STATUS_IS_OK(status)) {
1779                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1780                 correct = false;
1781         } else {
1782                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1783                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1784                         return false;
1785                 }
1786         }
1787
1788         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1789         if (NT_STATUS_IS_OK(status)) {
1790                 printf("READ lock2 succeeded! This is a locking bug\n");
1791                 correct = false;
1792         } else {
1793                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1794                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1795                         return false;
1796                 }
1797         }
1798
1799         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1800         if (!NT_STATUS_IS_OK(status)) {
1801                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1802         }
1803         cli_setpid(cli, 2);
1804         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1805                 printf("unlock at 100 succeeded! This is a locking bug\n");
1806                 correct = False;
1807         }
1808
1809         status = cli_unlock(cli, fnum1, 0, 4);
1810         if (NT_STATUS_IS_OK(status)) {
1811                 printf("unlock1 succeeded! This is a locking bug\n");
1812                 correct = false;
1813         } else {
1814                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1815                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1816                         return false;
1817                 }
1818         }
1819
1820         status = cli_unlock(cli, fnum1, 0, 8);
1821         if (NT_STATUS_IS_OK(status)) {
1822                 printf("unlock2 succeeded! This is a locking bug\n");
1823                 correct = false;
1824         } else {
1825                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1826                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1827                         return false;
1828                 }
1829         }
1830
1831         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1832         if (NT_STATUS_IS_OK(status)) {
1833                 printf("lock3 succeeded! This is a locking bug\n");
1834                 correct = false;
1835         } else {
1836                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1837                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1838                         return false;
1839                 }
1840         }
1841
1842         cli_setpid(cli, 1);
1843
1844         status = cli_close(cli, fnum1);
1845         if (!NT_STATUS_IS_OK(status)) {
1846                 printf("close1 failed (%s)\n", nt_errstr(status));
1847                 return False;
1848         }
1849
1850         status = cli_close(cli, fnum2);
1851         if (!NT_STATUS_IS_OK(status)) {
1852                 printf("close2 failed (%s)\n", nt_errstr(status));
1853                 return False;
1854         }
1855
1856         status = cli_close(cli, fnum3);
1857         if (!NT_STATUS_IS_OK(status)) {
1858                 printf("close3 failed (%s)\n", nt_errstr(status));
1859                 return False;
1860         }
1861
1862         if (!torture_close_connection(cli)) {
1863                 correct = False;
1864         }
1865
1866         printf("locktest2 finished\n");
1867
1868         return correct;
1869 }
1870
1871
1872 /*
1873   This test checks that 
1874
1875   1) the server supports the full offset range in lock requests
1876 */
1877 static bool run_locktest3(int dummy)
1878 {
1879         static struct cli_state *cli1, *cli2;
1880         const char *fname = "\\lockt3.lck";
1881         uint16_t fnum1, fnum2;
1882         int i;
1883         uint32_t offset;
1884         bool correct = True;
1885         NTSTATUS status;
1886
1887 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1888
1889         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1890                 return False;
1891         }
1892         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1893         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1894
1895         printf("starting locktest3\n");
1896
1897         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1898
1899         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1900                          &fnum1);
1901         if (!NT_STATUS_IS_OK(status)) {
1902                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1903                 return False;
1904         }
1905
1906         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1907         if (!NT_STATUS_IS_OK(status)) {
1908                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1909                 return False;
1910         }
1911
1912         for (offset=i=0;i<torture_numops;i++) {
1913                 NEXT_OFFSET;
1914
1915                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1916                 if (!NT_STATUS_IS_OK(status)) {
1917                         printf("lock1 %d failed (%s)\n", 
1918                                i,
1919                                nt_errstr(status));
1920                         return False;
1921                 }
1922
1923                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1924                 if (!NT_STATUS_IS_OK(status)) {
1925                         printf("lock2 %d failed (%s)\n", 
1926                                i,
1927                                nt_errstr(status));
1928                         return False;
1929                 }
1930         }
1931
1932         for (offset=i=0;i<torture_numops;i++) {
1933                 NEXT_OFFSET;
1934
1935                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1936                 if (NT_STATUS_IS_OK(status)) {
1937                         printf("error: lock1 %d succeeded!\n", i);
1938                         return False;
1939                 }
1940
1941                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1942                 if (NT_STATUS_IS_OK(status)) {
1943                         printf("error: lock2 %d succeeded!\n", i);
1944                         return False;
1945                 }
1946
1947                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1948                 if (NT_STATUS_IS_OK(status)) {
1949                         printf("error: lock3 %d succeeded!\n", i);
1950                         return False;
1951                 }
1952
1953                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1954                 if (NT_STATUS_IS_OK(status)) {
1955                         printf("error: lock4 %d succeeded!\n", i);
1956                         return False;
1957                 }
1958         }
1959
1960         for (offset=i=0;i<torture_numops;i++) {
1961                 NEXT_OFFSET;
1962
1963                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1964                 if (!NT_STATUS_IS_OK(status)) {
1965                         printf("unlock1 %d failed (%s)\n", 
1966                                i,
1967                                nt_errstr(status));
1968                         return False;
1969                 }
1970
1971                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1972                 if (!NT_STATUS_IS_OK(status)) {
1973                         printf("unlock2 %d failed (%s)\n", 
1974                                i,
1975                                nt_errstr(status));
1976                         return False;
1977                 }
1978         }
1979
1980         status = cli_close(cli1, fnum1);
1981         if (!NT_STATUS_IS_OK(status)) {
1982                 printf("close1 failed (%s)\n", nt_errstr(status));
1983                 return False;
1984         }
1985
1986         status = cli_close(cli2, fnum2);
1987         if (!NT_STATUS_IS_OK(status)) {
1988                 printf("close2 failed (%s)\n", nt_errstr(status));
1989                 return False;
1990         }
1991
1992         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1993         if (!NT_STATUS_IS_OK(status)) {
1994                 printf("unlink failed (%s)\n", nt_errstr(status));
1995                 return False;
1996         }
1997
1998         if (!torture_close_connection(cli1)) {
1999                 correct = False;
2000         }
2001
2002         if (!torture_close_connection(cli2)) {
2003                 correct = False;
2004         }
2005
2006         printf("finished locktest3\n");
2007
2008         return correct;
2009 }
2010
2011 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2012                            char *buf, off_t offset, size_t size,
2013                            size_t *nread, size_t expect)
2014 {
2015         NTSTATUS status;
2016         size_t l_nread;
2017
2018         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2019
2020         if(!NT_STATUS_IS_OK(status)) {
2021                 return false;
2022         } else if (l_nread != expect) {
2023                 return false;
2024         }
2025
2026         if (nread) {
2027                 *nread = l_nread;
2028         }
2029
2030         return true;
2031 }
2032
2033 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2034         printf("** "); correct = False; \
2035         }
2036
2037 /*
2038   looks at overlapping locks
2039 */
2040 static bool run_locktest4(int dummy)
2041 {
2042         static struct cli_state *cli1, *cli2;
2043         const char *fname = "\\lockt4.lck";
2044         uint16_t fnum1, fnum2, f;
2045         bool ret;
2046         char buf[1000];
2047         bool correct = True;
2048         NTSTATUS status;
2049
2050         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2051                 return False;
2052         }
2053
2054         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2055         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2056
2057         printf("starting locktest4\n");
2058
2059         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2060
2061         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2062         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2063
2064         memset(buf, 0, sizeof(buf));
2065
2066         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2067                               NULL);
2068         if (!NT_STATUS_IS_OK(status)) {
2069                 printf("Failed to create file: %s\n", nt_errstr(status));
2070                 correct = False;
2071                 goto fail;
2072         }
2073
2074         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2075               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2076         EXPECTED(ret, False);
2077         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2078
2079         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2080               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2081         EXPECTED(ret, True);
2082         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2083
2084         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2085               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2086         EXPECTED(ret, False);
2087         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2088
2089         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2090               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2091         EXPECTED(ret, True);
2092         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2093
2094         ret = (cli_setpid(cli1, 1),
2095               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2096               (cli_setpid(cli1, 2),
2097               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2098         EXPECTED(ret, False);
2099         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2100
2101         ret = (cli_setpid(cli1, 1),
2102               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2103               (cli_setpid(cli1, 2),
2104               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2105         EXPECTED(ret, True);
2106         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2107
2108         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2109               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2110         EXPECTED(ret, True);
2111         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2112
2113         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2114               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2115         EXPECTED(ret, False);
2116         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2117
2118         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2119               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2120         EXPECTED(ret, False);
2121         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2122
2123         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2124               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2125         EXPECTED(ret, True);
2126         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2127
2128         ret = (cli_setpid(cli1, 1),
2129              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2130              (cli_setpid(cli1, 2),
2131              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2132         EXPECTED(ret, False);
2133         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2134
2135         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2136               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2137               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2138         EXPECTED(ret, False);
2139         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2140
2141
2142         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2143               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2144         EXPECTED(ret, False);
2145         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2146
2147         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2148         ret = NT_STATUS_IS_OK(status);
2149         if (ret) {
2150                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2151                                       NULL);
2152                 ret = NT_STATUS_IS_OK(status);
2153         }
2154         EXPECTED(ret, False);
2155         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2156
2157
2158         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2159               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2160               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2161               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2162         EXPECTED(ret, True);
2163         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2164
2165
2166         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2167               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2168               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2169               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2170               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2171                                              150, 4, NULL))) &&
2172               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2173         EXPECTED(ret, True);
2174         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2175
2176         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2177               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2178               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2179                                            160, 4, NULL)) &&
2180               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2181         EXPECTED(ret, True);
2182         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2183
2184         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2185               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2186               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2187                                            170, 4, NULL)) &&
2188               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2189         EXPECTED(ret, True);
2190         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2191
2192         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2193               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2194               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2195               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2196                                             190, 4, NULL)) &&
2197               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2198         EXPECTED(ret, True);
2199         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2200
2201         cli_close(cli1, fnum1);
2202         cli_close(cli2, fnum2);
2203         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2204         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2205         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2206               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2207               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2208               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2209               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2210         cli_close(cli1, f);
2211         cli_close(cli1, fnum1);
2212         EXPECTED(ret, True);
2213         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
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         torture_close_connection(cli1);
2220         torture_close_connection(cli2);
2221
2222         printf("finished locktest4\n");
2223         return correct;
2224 }
2225
2226 /*
2227   looks at lock upgrade/downgrade.
2228 */
2229 static bool run_locktest5(int dummy)
2230 {
2231         static struct cli_state *cli1, *cli2;
2232         const char *fname = "\\lockt5.lck";
2233         uint16_t fnum1, fnum2, fnum3;
2234         bool ret;
2235         char buf[1000];
2236         bool correct = True;
2237         NTSTATUS status;
2238
2239         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2240                 return False;
2241         }
2242
2243         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2244         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2245
2246         printf("starting locktest5\n");
2247
2248         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2249
2250         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2251         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2252         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2253
2254         memset(buf, 0, sizeof(buf));
2255
2256         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2257                               NULL);
2258         if (!NT_STATUS_IS_OK(status)) {
2259                 printf("Failed to create file: %s\n", nt_errstr(status));
2260                 correct = False;
2261                 goto fail;
2262         }
2263
2264         /* Check for NT bug... */
2265         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2266               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2267         cli_close(cli1, fnum1);
2268         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2269         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2270         ret = NT_STATUS_IS_OK(status);
2271         EXPECTED(ret, True);
2272         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2273         cli_close(cli1, fnum1);
2274         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2275         cli_unlock(cli1, fnum3, 0, 1);
2276
2277         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2278               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2279         EXPECTED(ret, True);
2280         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2281
2282         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2283         ret = NT_STATUS_IS_OK(status);
2284         EXPECTED(ret, False);
2285
2286         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2287
2288         /* Unlock the process 2 lock. */
2289         cli_unlock(cli2, fnum2, 0, 4);
2290
2291         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2292         ret = NT_STATUS_IS_OK(status);
2293         EXPECTED(ret, False);
2294
2295         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2296
2297         /* Unlock the process 1 fnum3 lock. */
2298         cli_unlock(cli1, fnum3, 0, 4);
2299
2300         /* Stack 2 more locks here. */
2301         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2302               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2303
2304         EXPECTED(ret, True);
2305         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2306
2307         /* Unlock the first process lock, then check this was the WRITE lock that was
2308                 removed. */
2309
2310         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2311               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2312
2313         EXPECTED(ret, True);
2314         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2315
2316         /* Unlock the process 2 lock. */
2317         cli_unlock(cli2, fnum2, 0, 4);
2318
2319         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2320
2321         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2322                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2323                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2324
2325         EXPECTED(ret, True);
2326         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2327
2328         /* Ensure the next unlock fails. */
2329         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2330         EXPECTED(ret, False);
2331         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2332
2333         /* Ensure connection 2 can get a write lock. */
2334         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2335         ret = NT_STATUS_IS_OK(status);
2336         EXPECTED(ret, True);
2337
2338         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2339
2340
2341  fail:
2342         cli_close(cli1, fnum1);
2343         cli_close(cli2, fnum2);
2344         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2345         if (!torture_close_connection(cli1)) {
2346                 correct = False;
2347         }
2348         if (!torture_close_connection(cli2)) {
2349                 correct = False;
2350         }
2351
2352         printf("finished locktest5\n");
2353
2354         return correct;
2355 }
2356
2357 /*
2358   tries the unusual lockingX locktype bits
2359 */
2360 static bool run_locktest6(int dummy)
2361 {
2362         static struct cli_state *cli;
2363         const char *fname[1] = { "\\lock6.txt" };
2364         int i;
2365         uint16_t fnum;
2366         NTSTATUS status;
2367
2368         if (!torture_open_connection(&cli, 0)) {
2369                 return False;
2370         }
2371
2372         smbXcli_conn_set_sockopt(cli->conn, sockops);
2373
2374         printf("starting locktest6\n");
2375
2376         for (i=0;i<1;i++) {
2377                 printf("Testing %s\n", fname[i]);
2378
2379                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2380
2381                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2382                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2383                 cli_close(cli, fnum);
2384                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2385
2386                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2387                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2388                 cli_close(cli, fnum);
2389                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2390
2391                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2392         }
2393
2394         torture_close_connection(cli);
2395
2396         printf("finished locktest6\n");
2397         return True;
2398 }
2399
2400 static bool run_locktest7(int dummy)
2401 {
2402         struct cli_state *cli1;
2403         const char *fname = "\\lockt7.lck";
2404         uint16_t fnum1;
2405         char buf[200];
2406         bool correct = False;
2407         size_t nread;
2408         NTSTATUS status;
2409
2410         if (!torture_open_connection(&cli1, 0)) {
2411                 return False;
2412         }
2413
2414         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2415
2416         printf("starting locktest7\n");
2417
2418         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2419
2420         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2421
2422         memset(buf, 0, sizeof(buf));
2423
2424         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2425                               NULL);
2426         if (!NT_STATUS_IS_OK(status)) {
2427                 printf("Failed to create file: %s\n", nt_errstr(status));
2428                 goto fail;
2429         }
2430
2431         cli_setpid(cli1, 1);
2432
2433         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2434         if (!NT_STATUS_IS_OK(status)) {
2435                 printf("Unable to apply read lock on range 130:4, "
2436                        "error was %s\n", nt_errstr(status));
2437                 goto fail;
2438         } else {
2439                 printf("pid1 successfully locked range 130:4 for READ\n");
2440         }
2441
2442         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2443         if (!NT_STATUS_IS_OK(status)) {
2444                 printf("pid1 unable to read the range 130:4, error was %s\n",
2445                       nt_errstr(status));
2446                 goto fail;
2447         } else if (nread != 4) {
2448                 printf("pid1 unable to read the range 130:4, "
2449                        "recv %ld req %d\n", (unsigned long)nread, 4);
2450                 goto fail;
2451         } else {
2452                 printf("pid1 successfully read the range 130:4\n");
2453         }
2454
2455         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2456         if (!NT_STATUS_IS_OK(status)) {
2457                 printf("pid1 unable to write to the range 130:4, error was "
2458                        "%s\n", nt_errstr(status));
2459                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2460                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2461                         goto fail;
2462                 }
2463         } else {
2464                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2465                 goto fail;
2466         }
2467
2468         cli_setpid(cli1, 2);
2469
2470         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2471         if (!NT_STATUS_IS_OK(status)) {
2472                 printf("pid2 unable to read the range 130:4, error was %s\n",
2473                       nt_errstr(status));
2474                 goto fail;
2475         } else if (nread != 4) {
2476                 printf("pid2 unable to read the range 130:4, "
2477                        "recv %ld req %d\n", (unsigned long)nread, 4);
2478                 goto fail;
2479         } else {
2480                 printf("pid2 successfully read the range 130:4\n");
2481         }
2482
2483         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2484         if (!NT_STATUS_IS_OK(status)) {
2485                 printf("pid2 unable to write to the range 130:4, error was "
2486                        "%s\n", nt_errstr(status));
2487                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2488                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2489                         goto fail;
2490                 }
2491         } else {
2492                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2493                 goto fail;
2494         }
2495
2496         cli_setpid(cli1, 1);
2497         cli_unlock(cli1, fnum1, 130, 4);
2498
2499         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2500         if (!NT_STATUS_IS_OK(status)) {
2501                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2502                 goto fail;
2503         } else {
2504                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2505         }
2506
2507         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2508         if (!NT_STATUS_IS_OK(status)) {
2509                 printf("pid1 unable to read the range 130:4, error was %s\n",
2510                       nt_errstr(status));
2511                 goto fail;
2512         } else if (nread != 4) {
2513                 printf("pid1 unable to read the range 130:4, "
2514                        "recv %ld req %d\n", (unsigned long)nread, 4);
2515                 goto fail;
2516         } else {
2517                 printf("pid1 successfully read the range 130:4\n");
2518         }
2519
2520         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2521         if (!NT_STATUS_IS_OK(status)) {
2522                 printf("pid1 unable to write to the range 130:4, error was "
2523                        "%s\n", nt_errstr(status));
2524                 goto fail;
2525         } else {
2526                 printf("pid1 successfully wrote to the range 130:4\n");
2527         }
2528
2529         cli_setpid(cli1, 2);
2530
2531         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2532         if (!NT_STATUS_IS_OK(status)) {
2533                 printf("pid2 unable to read the range 130:4, error was "
2534                        "%s\n", nt_errstr(status));
2535                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2536                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2537                         goto fail;
2538                 }
2539         } else {
2540                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2541                        (unsigned long)nread);
2542                 goto fail;
2543         }
2544
2545         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2546         if (!NT_STATUS_IS_OK(status)) {
2547                 printf("pid2 unable to write to the range 130:4, error was "
2548                        "%s\n", nt_errstr(status));
2549                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2550                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2551                         goto fail;
2552                 }
2553         } else {
2554                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2555                 goto fail;
2556         }
2557
2558         cli_unlock(cli1, fnum1, 130, 0);
2559         correct = True;
2560
2561 fail:
2562         cli_close(cli1, fnum1);
2563         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2564         torture_close_connection(cli1);
2565
2566         printf("finished locktest7\n");
2567         return correct;
2568 }
2569
2570 /*
2571  * This demonstrates a problem with our use of GPFS share modes: A file
2572  * descriptor sitting in the pending close queue holding a GPFS share mode
2573  * blocks opening a file another time. Happens with Word 2007 temp files.
2574  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2575  * open is denied with NT_STATUS_SHARING_VIOLATION.
2576  */
2577
2578 static bool run_locktest8(int dummy)
2579 {
2580         struct cli_state *cli1;
2581         const char *fname = "\\lockt8.lck";
2582         uint16_t fnum1, fnum2;
2583         char buf[200];
2584         bool correct = False;
2585         NTSTATUS status;
2586
2587         if (!torture_open_connection(&cli1, 0)) {
2588                 return False;
2589         }
2590
2591         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2592
2593         printf("starting locktest8\n");
2594
2595         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2596
2597         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2598                           &fnum1);
2599         if (!NT_STATUS_IS_OK(status)) {
2600                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2601                 return false;
2602         }
2603
2604         memset(buf, 0, sizeof(buf));
2605
2606         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2607         if (!NT_STATUS_IS_OK(status)) {
2608                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2609                           nt_errstr(status));
2610                 goto fail;
2611         }
2612
2613         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2614         if (!NT_STATUS_IS_OK(status)) {
2615                 printf("Unable to apply read lock on range 1:1, error was "
2616                        "%s\n", nt_errstr(status));
2617                 goto fail;
2618         }
2619
2620         status = cli_close(cli1, fnum1);
2621         if (!NT_STATUS_IS_OK(status)) {
2622                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2623                 goto fail;
2624         }
2625
2626         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2627         if (!NT_STATUS_IS_OK(status)) {
2628                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2629                           nt_errstr(status));
2630                 goto fail;
2631         }
2632
2633         correct = true;
2634
2635 fail:
2636         cli_close(cli1, fnum1);
2637         cli_close(cli1, fnum2);
2638         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2639         torture_close_connection(cli1);
2640
2641         printf("finished locktest8\n");
2642         return correct;
2643 }
2644
2645 /*
2646  * This test is designed to be run in conjunction with
2647  * external NFS or POSIX locks taken in the filesystem.
2648  * It checks that the smbd server will block until the
2649  * lock is released and then acquire it. JRA.
2650  */
2651
2652 static bool got_alarm;
2653 static struct cli_state *alarm_cli;
2654
2655 static void alarm_handler(int dummy)
2656 {
2657         got_alarm = True;
2658 }
2659
2660 static void alarm_handler_parent(int dummy)
2661 {
2662         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2663 }
2664
2665 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2666 {
2667         int fd;
2668         char c = '\0';
2669         struct flock lock;
2670         const char *local_pathname = NULL;
2671         int ret;
2672
2673         local_pathname = talloc_asprintf(talloc_tos(),
2674                         "%s/%s", local_path, fname);
2675         if (!local_pathname) {
2676                 printf("child: alloc fail\n");
2677                 exit(1);
2678         }
2679
2680         unlink(local_pathname);
2681         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2682         if (fd == -1) {
2683                 printf("child: open of %s failed %s.\n",
2684                         local_pathname, strerror(errno));
2685                 exit(1);
2686         }
2687
2688         /* Now take a fcntl lock. */
2689         lock.l_type = F_WRLCK;
2690         lock.l_whence = SEEK_SET;
2691         lock.l_start = 0;
2692         lock.l_len = 4;
2693         lock.l_pid = getpid();
2694
2695         ret = fcntl(fd,F_SETLK,&lock);
2696         if (ret == -1) {
2697                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2698                         local_pathname, strerror(errno));
2699                 exit(1);
2700         } else {
2701                 printf("child: got lock 0:4 on file %s.\n",
2702                         local_pathname );
2703                 fflush(stdout);
2704         }
2705
2706         CatchSignal(SIGALRM, alarm_handler);
2707         alarm(5);
2708         /* Signal the parent. */
2709         if (write(write_fd, &c, 1) != 1) {
2710                 printf("child: start signal fail %s.\n",
2711                         strerror(errno));
2712                 exit(1);
2713         }
2714         alarm(0);
2715
2716         alarm(10);
2717         /* Wait for the parent to be ready. */
2718         if (read(read_fd, &c, 1) != 1) {
2719                 printf("child: reply signal fail %s.\n",
2720                         strerror(errno));
2721                 exit(1);
2722         }
2723         alarm(0);
2724
2725         sleep(5);
2726         close(fd);
2727         printf("child: released lock 0:4 on file %s.\n",
2728                 local_pathname );
2729         fflush(stdout);
2730         exit(0);
2731 }
2732
2733 static bool _run_locktest9X(const char *fname, int timeout)
2734 {
2735         struct cli_state *cli1;
2736         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2737         uint16_t fnum;
2738         bool correct = False;
2739         int pipe_in[2], pipe_out[2];
2740         pid_t child_pid;
2741         char c = '\0';
2742         int ret;
2743         struct timeval start;
2744         double seconds;
2745         NTSTATUS status;
2746
2747         printf("starting locktest9X: %s\n", fname);
2748
2749         if (local_path == NULL) {
2750                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2751                 return false;
2752         }
2753
2754         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2755                 return false;
2756         }
2757
2758         child_pid = fork();
2759         if (child_pid == -1) {
2760                 return false;
2761         }
2762
2763         if (child_pid == 0) {
2764                 /* Child. */
2765                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2766                 exit(0);
2767         }
2768
2769         close(pipe_out[0]);
2770         close(pipe_in[1]);
2771         pipe_out[0] = -1;
2772         pipe_in[1] = -1;
2773
2774         /* Parent. */
2775         ret = read(pipe_in[0], &c, 1);
2776         if (ret != 1) {
2777                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2778                         strerror(errno));
2779                 return false;
2780         }
2781
2782         if (!torture_open_connection(&cli1, 0)) {
2783                 return false;
2784         }
2785
2786         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2787
2788         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2789                           &fnum);
2790         if (!NT_STATUS_IS_OK(status)) {
2791                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2792                 return false;
2793         }
2794
2795         /* Ensure the child has the lock. */
2796         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2797         if (NT_STATUS_IS_OK(status)) {
2798                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2799                 goto fail;
2800         } else {
2801                 d_printf("Child has the lock.\n");
2802         }
2803
2804         /* Tell the child to wait 5 seconds then exit. */
2805         ret = write(pipe_out[1], &c, 1);
2806         if (ret != 1) {
2807                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2808                         strerror(errno));
2809                 goto fail;
2810         }
2811
2812         /* Wait 20 seconds for the lock. */
2813         alarm_cli = cli1;
2814         CatchSignal(SIGALRM, alarm_handler_parent);
2815         alarm(20);
2816
2817         start = timeval_current();
2818
2819         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2820         if (!NT_STATUS_IS_OK(status)) {
2821                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2822                        "%s\n", nt_errstr(status));
2823                 goto fail_nofd;
2824         }
2825         alarm(0);
2826
2827         seconds = timeval_elapsed(&start);
2828
2829         printf("Parent got the lock after %.2f seconds.\n",
2830                 seconds);
2831
2832         status = cli_close(cli1, fnum);
2833         if (!NT_STATUS_IS_OK(status)) {
2834                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2835                 goto fail;
2836         }
2837
2838         correct = true;
2839
2840 fail:
2841         cli_close(cli1, fnum);
2842         torture_close_connection(cli1);
2843
2844 fail_nofd:
2845
2846         printf("finished locktest9X: %s\n", fname);
2847         return correct;
2848 }
2849
2850 static bool run_locktest9a(int dummy)
2851 {
2852         return _run_locktest9X("lock9a.dat", -1);
2853 }
2854
2855 static bool run_locktest9b(int dummy)
2856 {
2857         return _run_locktest9X("lock9b.dat", 10000);
2858 }
2859
2860 struct locktest10_state {
2861         bool ok;
2862         bool done;
2863 };
2864
2865 static void locktest10_lockingx_done(struct tevent_req *subreq);
2866 static void locktest10_read_andx_done(struct tevent_req *subreq);
2867
2868 static bool run_locktest10(int dummy)
2869 {
2870         struct tevent_context *ev = NULL;
2871         struct cli_state *cli1 = NULL;
2872         struct cli_state *cli2 = NULL;
2873         struct smb1_lock_element lck = { 0 };
2874         struct tevent_req *reqs[2] = { NULL };
2875         struct tevent_req *smbreqs[2] = { NULL };
2876         const char fname[] = "\\lockt10.lck";
2877         uint16_t fnum1, fnum2;
2878         bool ret = false;
2879         bool ok;
2880         uint8_t data = 1;
2881         struct locktest10_state state = { .ok = true };
2882         NTSTATUS status;
2883
2884         printf("starting locktest10\n");
2885
2886         ev = samba_tevent_context_init(NULL);
2887         if (ev == NULL) {
2888                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2889                 goto done;
2890         }
2891
2892         ok = torture_open_connection(&cli1, 0);
2893         if (!ok) {
2894                 goto done;
2895         }
2896         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2897
2898         ok = torture_open_connection(&cli2, 1);
2899         if (!ok) {
2900                 goto done;
2901         }
2902         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2903
2904         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2905         if (!NT_STATUS_IS_OK(status)) {
2906                 d_fprintf(stderr,
2907                           "cli_openx failed: %s\n",
2908                           nt_errstr(status));
2909                 goto done;
2910         }
2911
2912         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2913         if (!NT_STATUS_IS_OK(status)) {
2914                 d_fprintf(stderr,
2915                           "cli_writeall failed: %s\n",
2916                           nt_errstr(status));
2917                 goto done;
2918         }
2919
2920         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2921         if (!NT_STATUS_IS_OK(status)) {
2922                 d_fprintf(stderr,
2923                           "cli_openx failed: %s\n",
2924                           nt_errstr(status));
2925                 goto done;
2926         }
2927
2928         status = cli_locktype(
2929                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2930         if (!NT_STATUS_IS_OK(status)) {
2931                 d_fprintf(stderr,
2932                           "cli_locktype failed: %s\n",
2933                           nt_errstr(status));
2934                 goto done;
2935         }
2936
2937         lck = (struct smb1_lock_element) {
2938                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2939         };
2940
2941         reqs[0] = cli_lockingx_create(
2942                 ev,                             /* mem_ctx */
2943                 ev,                             /* tevent_context */
2944                 cli1,                           /* cli */
2945                 fnum1,                          /* fnum */
2946                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2947                 0,                              /* newoplocklevel */
2948                 1,                              /* timeout */
2949                 0,                              /* num_unlocks */
2950                 NULL,                           /* unlocks */
2951                 1,                              /* num_locks */
2952                 &lck,                           /* locks */
2953                 &smbreqs[0]);                   /* psmbreq */
2954         if (reqs[0] == NULL) {
2955                 d_fprintf(stderr, "cli_lockingx_create failed\n");
2956                 goto done;
2957         }
2958         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2959
2960         reqs[1] = cli_read_andx_create(
2961                 ev,             /* mem_ctx */
2962                 ev,             /* ev */
2963                 cli1,           /* cli */
2964                 fnum1,          /* fnum */
2965                 0,              /* offset */
2966                 1,              /* size */
2967                 &smbreqs[1]);   /* psmbreq */
2968         if (reqs[1] == NULL) {
2969                 d_fprintf(stderr, "cli_read_andx_create failed\n");
2970                 goto done;
2971         }
2972         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2973
2974         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2975         if (!NT_STATUS_IS_OK(status)) {
2976                 d_fprintf(stderr,
2977                           "smb1cli_req_chain_submit failed: %s\n",
2978                           nt_errstr(status));
2979                 goto done;
2980         }
2981
2982         while (!state.done) {
2983                 tevent_loop_once(ev);
2984         }
2985
2986         torture_close_connection(cli1);
2987
2988         if (state.ok) {
2989                 ret = true;
2990         }
2991 done:
2992         return ret;
2993 }
2994
2995 static void locktest10_lockingx_done(struct tevent_req *subreq)
2996 {
2997         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2998         NTSTATUS status;
2999
3000         status = cli_lockingx_recv(subreq);
3001         TALLOC_FREE(subreq);
3002
3003         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3004                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3005                 state->ok = false;
3006         }
3007 }
3008
3009 static void locktest10_read_andx_done(struct tevent_req *subreq)
3010 {
3011         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3012         ssize_t received = -1;
3013         uint8_t *rcvbuf = NULL;
3014         NTSTATUS status;
3015
3016         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3017
3018         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3019                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3020                 state->ok = false;
3021         }
3022
3023         state->done = true;
3024         TALLOC_FREE(subreq);
3025 }
3026
3027 static bool run_locktest11(int dummy)
3028 {
3029         struct cli_state *cli1;
3030         const char *fname = "\\lockt11.lck";
3031         NTSTATUS status;
3032         uint16_t fnum;
3033         bool ret = false;
3034
3035         if (!torture_open_connection(&cli1, 0)) {
3036                 return false;
3037         }
3038
3039         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3040
3041         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3042
3043         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3044         if (!NT_STATUS_IS_OK(status)) {
3045                 d_fprintf(stderr,
3046                           "cli_openx returned %s\n",
3047                           nt_errstr(status));
3048                 return false;
3049         }
3050
3051         /*
3052          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3053          * returns NT_STATUS_OK
3054          */
3055
3056         status = cli_lockingx(
3057                 cli1,                           /* cli */
3058                 fnum,                           /* fnum */
3059                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3060                 0,                              /* newoplocklevel */
3061                 0,                              /* timeout */
3062                 0,                              /* num_unlocks */
3063                 NULL,                           /* unlocks */
3064                 0,                              /* num_locks */
3065                 NULL);                          /* locks */
3066
3067         if (!NT_STATUS_IS_OK(status)) {
3068                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3069                 goto fail;
3070         }
3071
3072         ret = true;
3073 fail:
3074         cli_close(cli1, fnum);
3075         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3076
3077         return ret;
3078 }
3079
3080 struct deferred_close_state {
3081         struct tevent_context *ev;
3082         struct cli_state *cli;
3083         uint16_t fnum;
3084 };
3085
3086 static void deferred_close_waited(struct tevent_req *subreq);
3087 static void deferred_close_done(struct tevent_req *subreq);
3088
3089 static struct tevent_req *deferred_close_send(
3090         TALLOC_CTX *mem_ctx,
3091         struct tevent_context *ev,
3092         int wait_secs,
3093         struct cli_state *cli,
3094         uint16_t fnum)
3095 {
3096         struct tevent_req *req = NULL, *subreq = NULL;
3097         struct deferred_close_state *state = NULL;
3098         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3099
3100         req = tevent_req_create(
3101                 mem_ctx, &state, struct deferred_close_state);
3102         if (req == NULL) {
3103                 return NULL;
3104         }
3105         state->ev = ev;
3106         state->cli = cli;
3107         state->fnum = fnum;
3108
3109         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3110         if (tevent_req_nomem(subreq, req)) {
3111                 return tevent_req_post(req, ev);
3112         }
3113         tevent_req_set_callback(subreq, deferred_close_waited, req);
3114         return req;
3115 }
3116
3117 static void deferred_close_waited(struct tevent_req *subreq)
3118 {
3119         struct tevent_req *req = tevent_req_callback_data(
3120                 subreq, struct tevent_req);
3121         struct deferred_close_state *state = tevent_req_data(
3122                 req, struct deferred_close_state);
3123         bool ok;
3124
3125         ok = tevent_wakeup_recv(subreq);
3126         TALLOC_FREE(subreq);
3127         if (!ok) {
3128                 tevent_req_oom(req);
3129                 return;
3130         }
3131
3132         subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3133         if (tevent_req_nomem(subreq, req)) {
3134                 return;
3135         }
3136         tevent_req_set_callback(subreq, deferred_close_done, req);
3137 }
3138
3139 static void deferred_close_done(struct tevent_req *subreq)
3140 {
3141         NTSTATUS status = cli_close_recv(subreq);
3142         tevent_req_simple_finish_ntstatus(subreq, status);
3143 }
3144
3145 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3146 {
3147         return tevent_req_simple_recv_ntstatus(req);
3148 }
3149
3150 struct lockread_state {
3151         struct smb1_lock_element lck;
3152         struct tevent_req *reqs[2];
3153         struct tevent_req *smbreqs[2];
3154         NTSTATUS lock_status;
3155         NTSTATUS read_status;
3156         uint8_t *readbuf;
3157 };
3158
3159 static void lockread_lockingx_done(struct tevent_req *subreq);
3160 static void lockread_read_andx_done(struct tevent_req *subreq);
3161
3162 static struct tevent_req *lockread_send(
3163         TALLOC_CTX *mem_ctx,
3164         struct tevent_context *ev,
3165         struct cli_state *cli,
3166         uint16_t fnum)
3167 {
3168         struct tevent_req *req = NULL;
3169         struct lockread_state *state = NULL;
3170         NTSTATUS status;
3171
3172         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3173         if (req == NULL) {
3174                 return NULL;
3175         }
3176
3177         state->lck = (struct smb1_lock_element) {
3178                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3179         };
3180
3181         state->reqs[0] = cli_lockingx_create(
3182                 ev,                             /* mem_ctx */
3183                 ev,                             /* tevent_context */
3184                 cli,                            /* cli */
3185                 fnum,                           /* fnum */
3186                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3187                 0,                              /* newoplocklevel */
3188                 10000,                          /* timeout */
3189                 0,                              /* num_unlocks */
3190                 NULL,                           /* unlocks */
3191                 1,                              /* num_locks */
3192                 &state->lck,                    /* locks */
3193                 &state->smbreqs[0]);            /* psmbreq */
3194         if (tevent_req_nomem(state->reqs[0], req)) {
3195                 return tevent_req_post(req, ev);
3196         }
3197         tevent_req_set_callback(
3198                 state->reqs[0], lockread_lockingx_done, req);
3199
3200         state->reqs[1] = cli_read_andx_create(
3201                 ev,             /* mem_ctx */
3202                 ev,             /* ev */
3203                 cli,            /* cli */
3204                 fnum,           /* fnum */
3205                 0,              /* offset */
3206                 1,              /* size */
3207                 &state->smbreqs[1]);    /* psmbreq */
3208         if (tevent_req_nomem(state->reqs[1], req)) {
3209                 return tevent_req_post(req, ev);
3210         }
3211         tevent_req_set_callback(
3212                 state->reqs[1], lockread_read_andx_done, req);
3213
3214         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3215         if (tevent_req_nterror(req, status)) {
3216                 return tevent_req_post(req, ev);
3217         }
3218         return req;
3219 }
3220
3221 static void lockread_lockingx_done(struct tevent_req *subreq)
3222 {
3223         struct tevent_req *req = tevent_req_callback_data(
3224                 subreq, struct tevent_req);
3225         struct lockread_state *state = tevent_req_data(
3226                 req, struct lockread_state);
3227         state->lock_status = cli_lockingx_recv(subreq);
3228         TALLOC_FREE(subreq);
3229         d_fprintf(stderr,
3230                   "lockingx returned %s\n",
3231                   nt_errstr(state->lock_status));
3232 }
3233
3234 static void lockread_read_andx_done(struct tevent_req *subreq)
3235 {
3236         struct tevent_req *req = tevent_req_callback_data(
3237                 subreq, struct tevent_req);
3238         struct lockread_state *state = tevent_req_data(
3239                 req, struct lockread_state);
3240         ssize_t received = -1;
3241         uint8_t *rcvbuf = NULL;
3242
3243         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3244
3245         d_fprintf(stderr,
3246                   "read returned %s\n",
3247                   nt_errstr(state->read_status));
3248
3249         if (!NT_STATUS_IS_OK(state->read_status)) {
3250                 TALLOC_FREE(subreq);
3251                 tevent_req_done(req);
3252                 return;
3253         }
3254
3255         if (received > 0) {
3256                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3257                 TALLOC_FREE(subreq);
3258                 if (tevent_req_nomem(state->readbuf, req)) {
3259                         return;
3260                 }
3261         }
3262         TALLOC_FREE(subreq);
3263         tevent_req_done(req);
3264 }
3265
3266 static NTSTATUS lockread_recv(
3267         struct tevent_req *req,
3268         NTSTATUS *lock_status,
3269         NTSTATUS *read_status,
3270         TALLOC_CTX *mem_ctx,
3271         uint8_t **read_buf)
3272 {
3273         struct lockread_state *state = tevent_req_data(
3274                 req, struct lockread_state);
3275         NTSTATUS status;
3276
3277         if (tevent_req_is_nterror(req, &status)) {
3278                 return status;
3279         }
3280
3281         *lock_status = state->lock_status;
3282         *read_status = state->read_status;
3283         if (state->readbuf != NULL) {
3284                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3285         } else {
3286                 *read_buf = NULL;
3287         }
3288
3289         return NT_STATUS_OK;
3290 }
3291
3292 struct lock12_state {
3293         uint8_t dummy;
3294 };
3295
3296 static void lock12_closed(struct tevent_req *subreq);
3297 static void lock12_read(struct tevent_req *subreq);
3298
3299 static struct tevent_req *lock12_send(
3300         TALLOC_CTX *mem_ctx,
3301         struct tevent_context *ev,
3302         struct cli_state *cli,
3303         uint16_t fnum1,
3304         uint16_t fnum2)
3305 {
3306         struct tevent_req *req = NULL, *subreq = NULL;
3307         struct lock12_state *state = NULL;
3308
3309         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3310         if (req == NULL) {
3311                 return NULL;
3312         }
3313
3314         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3315         if (tevent_req_nomem(subreq, req)) {
3316                 return tevent_req_post(req, ev);
3317         }
3318         tevent_req_set_callback(subreq, lock12_closed, req);
3319
3320         subreq = lockread_send(state, ev, cli, fnum2);
3321         if (tevent_req_nomem(subreq, req)) {
3322                 return tevent_req_post(req, ev);
3323         }
3324         tevent_req_set_callback(subreq, lock12_read, req);
3325
3326         return req;
3327 }
3328
3329 static void lock12_closed(struct tevent_req *subreq)
3330 {
3331         struct tevent_req *req = tevent_req_callback_data(
3332                 subreq, struct tevent_req);
3333         NTSTATUS status;
3334
3335         status = deferred_close_recv(subreq);
3336         TALLOC_FREE(subreq);
3337         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3338         if (tevent_req_nterror(req, status)) {
3339                 return;
3340         }
3341 }
3342
3343 static void lock12_read(struct tevent_req *subreq)
3344 {
3345         struct tevent_req *req = tevent_req_callback_data(
3346                 subreq, struct tevent_req);
3347         struct lock12_state *state = tevent_req_data(
3348                 req, struct lock12_state);
3349         NTSTATUS status, lock_status, read_status;
3350         uint8_t *buf = NULL;
3351
3352         status = lockread_recv(
3353                 subreq, &lock_status, &read_status, state, &buf);
3354         TALLOC_FREE(subreq);
3355         if (tevent_req_nterror(req, status) ||
3356             tevent_req_nterror(req, lock_status) ||
3357             tevent_req_nterror(req, read_status)) {
3358                 return;
3359         }
3360         tevent_req_done(req);
3361 }
3362
3363 static NTSTATUS lock12_recv(struct tevent_req *req)
3364
3365 {
3366         NTSTATUS status;
3367
3368         if (tevent_req_is_nterror(req, &status)) {
3369                 return status;
3370         }
3371         return NT_STATUS_OK;
3372 }
3373
3374 static bool run_locktest12(int dummy)
3375 {
3376         struct tevent_context *ev = NULL;
3377         struct tevent_req *req = NULL;
3378         struct cli_state *cli = NULL;
3379         const char fname[] = "\\lockt12.lck";
3380         uint16_t fnum1, fnum2;
3381         bool ret = false;
3382         bool ok;
3383         uint8_t data = 1;
3384         NTSTATUS status;
3385
3386         printf("starting locktest12\n");
3387
3388         ev = samba_tevent_context_init(NULL);
3389         if (ev == NULL) {
3390                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3391                 goto done;
3392         }
3393
3394         ok = torture_open_connection(&cli, 0);
3395         if (!ok) {
3396                 goto done;
3397         }
3398         smbXcli_conn_set_sockopt(cli->conn, sockops);
3399
3400         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3401         if (!NT_STATUS_IS_OK(status)) {
3402                 d_fprintf(stderr,
3403                           "cli_openx failed: %s\n",
3404                           nt_errstr(status));
3405                 goto done;
3406         }
3407
3408         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3409         if (!NT_STATUS_IS_OK(status)) {
3410                 d_fprintf(stderr,
3411                           "cli_openx failed: %s\n",
3412                           nt_errstr(status));
3413                 goto done;
3414         }
3415
3416         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3417         if (!NT_STATUS_IS_OK(status)) {
3418                 d_fprintf(stderr,
3419                           "cli_writeall failed: %s\n",
3420                           nt_errstr(status));
3421                 goto done;
3422         }
3423
3424         status = cli_locktype(
3425                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3426         if (!NT_STATUS_IS_OK(status)) {
3427                 d_fprintf(stderr,
3428                           "cli_locktype failed: %s\n",
3429                           nt_errstr(status));
3430                 goto done;
3431         }
3432
3433         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3434         if (req == NULL) {
3435                 d_fprintf(stderr, "lock12_send failed\n");
3436                 goto done;
3437         }
3438
3439         ok = tevent_req_poll_ntstatus(req, ev, &status);
3440         if (!ok) {
3441                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3442                 goto done;
3443         }
3444
3445         if (!NT_STATUS_IS_OK(status)) {
3446                 d_fprintf(stderr,
3447                           "tevent_req_poll_ntstatus returned %s\n",
3448                           nt_errstr(status));
3449                 goto done;
3450         }
3451
3452         status = lock12_recv(req);
3453         if (!NT_STATUS_IS_OK(status)) {
3454                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3455                 goto done;
3456         }
3457
3458         ret = true;
3459 done:
3460         if (cli != NULL) {
3461                 torture_close_connection(cli);
3462         }
3463         return ret;
3464 }
3465
3466 struct lock_ntcancel_state {
3467         struct timeval start;
3468         struct smb1_lock_element lck;
3469         struct tevent_req *subreq;
3470 };
3471
3472 static void lock_ntcancel_waited(struct tevent_req *subreq);
3473 static void lock_ntcancel_done(struct tevent_req *subreq);
3474
3475 static struct tevent_req *lock_ntcancel_send(
3476         TALLOC_CTX *mem_ctx,
3477         struct tevent_context *ev,
3478         struct cli_state *cli,
3479         uint16_t fnum)
3480 {
3481         struct tevent_req *req = NULL, *subreq = NULL;
3482         struct lock_ntcancel_state *state = NULL;
3483
3484         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3485         if (req == NULL) {
3486                 return NULL;
3487         }
3488         state->lck = (struct smb1_lock_element) {
3489                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3490         };
3491         state->start = timeval_current();
3492
3493         state->subreq = cli_lockingx_send(
3494                 state,                          /* mem_ctx */
3495                 ev,                             /* tevent_context */
3496                 cli,                            /* cli */
3497                 fnum,                           /* fnum */
3498                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3499                 0,                              /* newoplocklevel */
3500                 10000,                          /* timeout */
3501                 0,                              /* num_unlocks */
3502                 NULL,                           /* unlocks */
3503                 1,                              /* num_locks */
3504                 &state->lck);                   /* locks */
3505         if (tevent_req_nomem(state->subreq, req)) {
3506                 return tevent_req_post(req, ev);
3507         }
3508         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3509
3510         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3511         if (tevent_req_nomem(subreq, req)) {
3512                 return tevent_req_post(req, ev);
3513         }
3514         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3515         return req;
3516 }
3517
3518 static void lock_ntcancel_waited(struct tevent_req *subreq)
3519 {
3520         struct tevent_req *req = tevent_req_callback_data(
3521                 subreq, struct tevent_req);
3522         struct lock_ntcancel_state *state = tevent_req_data(
3523                 req, struct lock_ntcancel_state);
3524         bool ok;
3525
3526         ok = tevent_wakeup_recv(subreq);
3527         TALLOC_FREE(subreq);
3528         if (!ok) {
3529                 tevent_req_oom(req);
3530                 return;
3531         }
3532
3533         ok = tevent_req_cancel(state->subreq);
3534         if (!ok) {
3535                 d_fprintf(stderr, "Could not cancel subreq\n");
3536                 tevent_req_oom(req);
3537                 return;
3538         }
3539 }
3540
3541 static void lock_ntcancel_done(struct tevent_req *subreq)
3542 {
3543         struct tevent_req *req = tevent_req_callback_data(
3544                 subreq, struct tevent_req);
3545         struct lock_ntcancel_state *state = tevent_req_data(
3546                 req, struct lock_ntcancel_state);
3547         NTSTATUS status;
3548         double elapsed;
3549
3550         status = cli_lockingx_recv(subreq);
3551         TALLOC_FREE(subreq);
3552
3553         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3554                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3555                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3556                 return;
3557         }
3558
3559         elapsed = timeval_elapsed(&state->start);
3560
3561         if (elapsed > 3) {
3562                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3563                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3564                 return;
3565         }
3566
3567         tevent_req_done(req);
3568 }
3569
3570 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3571 {
3572         return tevent_req_simple_recv_ntstatus(req);
3573 }
3574
3575 static bool run_locktest13(int dummy)
3576 {
3577         struct tevent_context *ev = NULL;
3578         struct tevent_req *req = NULL;
3579         struct cli_state *cli = NULL;
3580         const char fname[] = "\\lockt13.lck";
3581         uint16_t fnum1, fnum2;
3582         bool ret = false;
3583         bool ok;
3584         uint8_t data = 1;
3585         NTSTATUS status;
3586
3587         printf("starting locktest13\n");
3588
3589         ev = samba_tevent_context_init(NULL);
3590         if (ev == NULL) {
3591                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3592                 goto done;
3593         }
3594
3595         ok = torture_open_connection(&cli, 0);
3596         if (!ok) {
3597                 goto done;
3598         }
3599         smbXcli_conn_set_sockopt(cli->conn, sockops);
3600
3601         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3602         if (!NT_STATUS_IS_OK(status)) {
3603                 d_fprintf(stderr,
3604                           "cli_openx failed: %s\n",
3605                           nt_errstr(status));
3606                 goto done;
3607         }
3608
3609         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3610         if (!NT_STATUS_IS_OK(status)) {
3611                 d_fprintf(stderr,
3612                           "cli_openx failed: %s\n",
3613                           nt_errstr(status));
3614                 goto done;
3615         }
3616
3617         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3618         if (!NT_STATUS_IS_OK(status)) {
3619                 d_fprintf(stderr,
3620                           "cli_writeall failed: %s\n",
3621                           nt_errstr(status));
3622                 goto done;
3623         }
3624
3625         status = cli_locktype(
3626                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3627         if (!NT_STATUS_IS_OK(status)) {
3628                 d_fprintf(stderr,
3629                           "cli_locktype failed: %s\n",
3630                           nt_errstr(status));
3631                 goto done;
3632         }
3633
3634         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3635         if (req == NULL) {
3636                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3637                 goto done;
3638         }
3639
3640         ok = tevent_req_poll_ntstatus(req, ev, &status);
3641         if (!ok) {
3642                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3643                 goto done;
3644         }
3645
3646         if (!NT_STATUS_IS_OK(status)) {
3647                 d_fprintf(stderr,
3648                           "tevent_req_poll_ntstatus returned %s\n",
3649                           nt_errstr(status));
3650                 goto done;
3651         }
3652
3653         status = lock_ntcancel_recv(req);
3654         if (!NT_STATUS_IS_OK(status)) {
3655                 d_fprintf(stderr,
3656                           "lock_ntcancel returned %s\n",
3657                           nt_errstr(status));
3658                 goto done;
3659         }
3660
3661         ret = true;
3662 done:
3663         if (cli != NULL) {
3664                 torture_close_connection(cli);
3665         }
3666         return ret;
3667 }
3668
3669 /*
3670 test whether fnums and tids open on one VC are available on another (a major
3671 security hole)
3672 */
3673 static bool run_fdpasstest(int dummy)
3674 {
3675         struct cli_state *cli1, *cli2;
3676         const char *fname = "\\fdpass.tst";
3677         uint16_t fnum1;
3678         char buf[1024];
3679         NTSTATUS status;
3680
3681         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3682                 return False;
3683         }
3684         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3685         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3686
3687         printf("starting fdpasstest\n");
3688
3689         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3690
3691         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3692                           &fnum1);
3693         if (!NT_STATUS_IS_OK(status)) {
3694                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3695                 return False;
3696         }
3697
3698         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3699                               13, NULL);
3700         if (!NT_STATUS_IS_OK(status)) {
3701                 printf("write failed (%s)\n", nt_errstr(status));
3702                 return False;
3703         }
3704
3705         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3706         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3707         cli_setpid(cli2, cli_getpid(cli1));
3708
3709         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3710                 printf("read succeeded! nasty security hole [%s]\n", buf);
3711                 return false;
3712         }
3713
3714         cli_close(cli1, fnum1);
3715         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3716
3717         torture_close_connection(cli1);
3718         torture_close_connection(cli2);
3719
3720         printf("finished fdpasstest\n");
3721         return True;
3722 }
3723
3724 static bool run_fdsesstest(int dummy)
3725 {
3726         struct cli_state *cli;
3727         uint16_t new_vuid;
3728         uint16_t saved_vuid;
3729         uint32_t new_cnum;
3730         uint32_t saved_cnum;
3731         const char *fname = "\\fdsess.tst";
3732         const char *fname1 = "\\fdsess1.tst";
3733         uint16_t fnum1;
3734         uint16_t fnum2;
3735         char buf[1024];
3736         bool ret = True;
3737         NTSTATUS status;
3738
3739         if (!torture_open_connection(&cli, 0))
3740                 return False;
3741         smbXcli_conn_set_sockopt(cli->conn, sockops);
3742
3743         if (!torture_cli_session_setup2(cli, &new_vuid))
3744                 return False;
3745
3746         saved_cnum = cli_state_get_tid(cli);
3747         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3748                 return False;
3749         new_cnum = cli_state_get_tid(cli);
3750         cli_state_set_tid(cli, saved_cnum);
3751
3752         printf("starting fdsesstest\n");
3753
3754         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3755         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3756
3757         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3758         if (!NT_STATUS_IS_OK(status)) {
3759                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3760                 return False;
3761         }
3762
3763         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3764                               NULL);
3765         if (!NT_STATUS_IS_OK(status)) {
3766                 printf("write failed (%s)\n", nt_errstr(status));
3767                 return False;
3768         }
3769
3770         saved_vuid = cli_state_get_uid(cli);
3771         cli_state_set_uid(cli, new_vuid);
3772
3773         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3774                 printf("read succeeded with different vuid! "
3775                        "nasty security hole [%s]\n", buf);
3776                 ret = false;
3777         }
3778         /* Try to open a file with different vuid, samba cnum. */
3779         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3780                 printf("create with different vuid, same cnum succeeded.\n");
3781                 cli_close(cli, fnum2);
3782                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3783         } else {
3784                 printf("create with different vuid, same cnum failed.\n");
3785                 printf("This will cause problems with service clients.\n");
3786                 ret = False;
3787         }
3788
3789         cli_state_set_uid(cli, saved_vuid);
3790
3791         /* Try with same vuid, different cnum. */
3792         cli_state_set_tid(cli, new_cnum);
3793
3794         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3795                 printf("read succeeded with different cnum![%s]\n", buf);
3796                 ret = false;
3797         }
3798
3799         cli_state_set_tid(cli, saved_cnum);
3800         cli_close(cli, fnum1);
3801         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3802
3803         torture_close_connection(cli);
3804
3805         printf("finished fdsesstest\n");
3806         return ret;
3807 }
3808
3809 /*
3810   This test checks that 
3811
3812   1) the server does not allow an unlink on a file that is open
3813 */
3814 static bool run_unlinktest(int dummy)
3815 {
3816         struct cli_state *cli;
3817         const char *fname = "\\unlink.tst";
3818         uint16_t fnum;
3819         bool correct = True;
3820         NTSTATUS status;
3821
3822         if (!torture_open_connection(&cli, 0)) {
3823                 return False;
3824         }
3825
3826         smbXcli_conn_set_sockopt(cli->conn, sockops);
3827
3828         printf("starting unlink test\n");
3829
3830         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3831
3832         cli_setpid(cli, 1);
3833
3834         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3835         if (!NT_STATUS_IS_OK(status)) {
3836                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3837                 return False;
3838         }
3839
3840         status = cli_unlink(cli, fname,
3841                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3842         if (NT_STATUS_IS_OK(status)) {
3843                 printf("error: server allowed unlink on an open file\n");
3844                 correct = False;
3845         } else {
3846                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3847                                       NT_STATUS_SHARING_VIOLATION);
3848         }
3849
3850         cli_close(cli, fnum);
3851         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3852
3853         if (!torture_close_connection(cli)) {
3854                 correct = False;
3855         }
3856
3857         printf("unlink test finished\n");
3858
3859         return correct;
3860 }
3861
3862
3863 /*
3864 test how many open files this server supports on the one socket
3865 */
3866 static bool run_maxfidtest(int dummy)
3867 {
3868         struct cli_state *cli;
3869         fstring fname;
3870         uint16_t fnums[0x11000];
3871         int i;
3872         int retries=4;
3873         bool correct = True;
3874         NTSTATUS status;
3875
3876         cli = current_cli;
3877
3878         if (retries <= 0) {
3879                 printf("failed to connect\n");
3880                 return False;
3881         }
3882
3883         smbXcli_conn_set_sockopt(cli->conn, sockops);
3884
3885         for (i=0; i<0x11000; i++) {
3886                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3887                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3888                                   &fnums[i]);
3889                 if (!NT_STATUS_IS_OK(status)) {
3890                         printf("open of %s failed (%s)\n", 
3891                                fname, nt_errstr(status));
3892                         printf("maximum fnum is %d\n", i);
3893                         break;
3894                 }
3895                 printf("%6d\r", i);
3896         }
3897         printf("%6d\n", i);
3898         i--;
3899
3900         printf("cleaning up\n");
3901         for (;i>=0;i--) {
3902                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3903                 cli_close(cli, fnums[i]);
3904
3905                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3906                 if (!NT_STATUS_IS_OK(status)) {
3907                         printf("unlink of %s failed (%s)\n", 
3908                                fname, nt_errstr(status));
3909                         correct = False;
3910                 }
3911                 printf("%6d\r", i);
3912         }
3913         printf("%6d\n", 0);
3914
3915         printf("maxfid test finished\n");
3916         if (!torture_close_connection(cli)) {
3917                 correct = False;
3918         }
3919         return correct;
3920 }
3921
3922 /* generate a random buffer */
3923 static void rand_buf(char *buf, int len)
3924 {
3925         while (len--) {
3926                 *buf = (char)sys_random();
3927                 buf++;
3928         }
3929 }
3930
3931 /* send smb negprot commands, not reading the response */
3932 static bool run_negprot_nowait(int dummy)
3933 {
3934         struct tevent_context *ev;
3935         int i;
3936         struct cli_state *cli;
3937         bool correct = True;
3938
3939         printf("starting negprot nowait test\n");
3940
3941         ev = samba_tevent_context_init(talloc_tos());
3942         if (ev == NULL) {
3943                 return false;
3944         }
3945
3946         if (!(cli = open_nbt_connection())) {
3947                 TALLOC_FREE(ev);
3948                 return False;
3949         }
3950
3951         for (i=0;i<50000;i++) {
3952                 struct tevent_req *req;
3953
3954                 req = smbXcli_negprot_send(
3955                         ev,
3956                         ev,
3957                         cli->conn,
3958                         cli->timeout,
3959                         PROTOCOL_CORE,
3960                         PROTOCOL_NT1,
3961                         0,
3962                         NULL);
3963                 if (req == NULL) {
3964                         TALLOC_FREE(ev);
3965                         return false;
3966                 }
3967                 if (!tevent_req_poll(req, ev)) {
3968                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3969                                   strerror(errno));
3970                         TALLOC_FREE(ev);
3971                         return false;
3972                 }
3973                 TALLOC_FREE(req);
3974         }
3975
3976         if (torture_close_connection(cli)) {
3977                 correct = False;
3978         }
3979
3980         printf("finished negprot nowait test\n");
3981
3982         return correct;
3983 }
3984
3985 /* send smb negprot commands, not reading the response */
3986 static bool run_bad_nbt_session(int dummy)
3987 {
3988         struct nmb_name called, calling;
3989         struct sockaddr_storage ss;
3990         NTSTATUS status;
3991         int fd;
3992         bool ret;
3993
3994         printf("starting bad nbt session test\n");
3995
3996         make_nmb_name(&calling, myname, 0x0);
3997         make_nmb_name(&called , host, 0x20);
3998
3999         if (!resolve_name(host, &ss, 0x20, true)) {
4000                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4001                 return false;
4002         }
4003
4004         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4005         if (!NT_STATUS_IS_OK(status)) {
4006                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4007                           nt_errstr(status));
4008                 return false;
4009         }
4010
4011         ret = cli_bad_session_request(fd, &calling, &called);
4012         close(fd);
4013         if (!ret) {
4014                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4015                           nt_errstr(status));
4016                 return false;
4017         }
4018
4019         printf("finished bad nbt session test\n");
4020         return true;
4021 }
4022
4023 /* send random IPC commands */
4024 static bool run_randomipc(int dummy)
4025 {
4026         char *rparam = NULL;
4027         char *rdata = NULL;
4028         unsigned int rdrcnt,rprcnt;
4029         char param[1024];
4030         int api, param_len, i;
4031         struct cli_state *cli;
4032         bool correct = True;
4033         int count = 50000;
4034
4035         printf("starting random ipc test\n");
4036
4037         if (!torture_open_connection(&cli, 0)) {
4038                 return False;
4039         }
4040
4041         for (i=0;i<count;i++) {
4042                 api = sys_random() % 500;
4043                 param_len = (sys_random() % 64);
4044
4045                 rand_buf(param, param_len);
4046
4047                 SSVAL(param,0,api); 
4048
4049                 cli_api(cli, 
4050                         param, param_len, 8,  
4051                         NULL, 0, CLI_BUFFER_SIZE,
4052                         &rparam, &rprcnt,     
4053                         &rdata, &rdrcnt);
4054                 if (i % 100 == 0) {
4055                         printf("%d/%d\r", i,count);
4056                 }
4057         }
4058         printf("%d/%d\n", i, count);
4059
4060         if (!torture_close_connection(cli)) {
4061                 correct = False;
4062         }
4063
4064         SAFE_FREE(rparam);
4065         SAFE_FREE(rdata);
4066
4067         printf("finished random ipc test\n");
4068
4069         return correct;
4070 }
4071
4072
4073
4074 static void browse_callback(const char *sname, uint32_t stype,
4075                             const char *comment, void *state)
4076 {
4077         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4078 }
4079
4080
4081
4082 /*
4083   This test checks the browse list code
4084
4085 */
4086 static bool run_browsetest(int dummy)
4087 {
4088         static struct cli_state *cli;
4089         bool correct = True;
4090
4091         printf("starting browse test\n");
4092
4093         if (!torture_open_connection(&cli, 0)) {
4094                 return False;
4095         }
4096
4097         printf("domain list:\n");
4098         cli_NetServerEnum(cli, cli->server_domain, 
4099                           SV_TYPE_DOMAIN_ENUM,
4100                           browse_callback, NULL);
4101
4102         printf("machine list:\n");
4103         cli_NetServerEnum(cli, cli->server_domain, 
4104                           SV_TYPE_ALL,
4105                           browse_callback, NULL);
4106
4107         if (!torture_close_connection(cli)) {
4108                 correct = False;
4109         }
4110
4111         printf("browse test finished\n");
4112
4113         return correct;
4114
4115 }
4116
4117 static bool check_attributes(struct cli_state *cli,
4118                                 const char *fname,
4119                                 uint32_t expected_attrs)
4120 {
4121         uint32_t attrs = 0;
4122         NTSTATUS status = cli_getatr(cli,
4123                                 fname,
4124                                 &attrs,
4125                                 NULL,
4126                                 NULL);
4127         if (!NT_STATUS_IS_OK(status)) {
4128                 printf("cli_getatr failed with %s\n",
4129                         nt_errstr(status));
4130                 return false;
4131         }
4132         if (attrs != expected_attrs) {
4133                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4134                         (unsigned int)attrs,
4135                         (unsigned int)expected_attrs);
4136                 return false;
4137         }
4138         return true;
4139 }
4140
4141 /*
4142   This checks how the getatr calls works
4143 */
4144 static bool run_attrtest(int dummy)
4145 {
4146         struct cli_state *cli;
4147         uint16_t fnum;
4148         time_t t, t2;
4149         const char *fname = "\\attrib123456789.tst";
4150         bool correct = True;
4151         NTSTATUS status;
4152
4153         printf("starting attrib test\n");
4154
4155         if (!torture_open_connection(&cli, 0)) {
4156                 return False;
4157         }
4158
4159         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4160         status = cli_unlink(cli, fname, 0x20000);
4161         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4162                 correct = false;
4163                 goto out;
4164         }
4165
4166         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4167         cli_openx(cli, fname, 
4168                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4169         cli_close(cli, fnum);
4170
4171         status = cli_getatr(cli, fname, NULL, NULL, &t);
4172         if (!NT_STATUS_IS_OK(status)) {
4173                 printf("getatr failed (%s)\n", nt_errstr(status));
4174                 correct = False;
4175         }
4176
4177         if (labs(t - time(NULL)) > 60*60*24*10) {
4178                 printf("ERROR: SMBgetatr bug. time is %s",
4179                        ctime(&t));
4180                 t = time(NULL);
4181                 correct = True;
4182         }
4183
4184         t2 = t-60*60*24; /* 1 day ago */
4185
4186         /* Ensure we can't set with out-of-range (unknown) attribute. */
4187         status = cli_setatr(cli, fname, 0x20000, t2);
4188         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4189                 correct = false;
4190                 goto out;
4191         }
4192
4193         status = cli_setatr(cli, fname, 0, t2);
4194         if (!NT_STATUS_IS_OK(status)) {
4195                 printf("setatr failed (%s)\n", nt_errstr(status));
4196                 correct = True;
4197         }
4198
4199         status = cli_getatr(cli, fname, NULL, NULL, &t);
4200         if (!NT_STATUS_IS_OK(status)) {
4201                 printf("getatr failed (%s)\n", nt_errstr(status));
4202                 correct = True;
4203         }
4204
4205         if (t != t2) {
4206                 printf("ERROR: getatr/setatr bug. times are\n%s",
4207                        ctime(&t));
4208                 printf("%s", ctime(&t2));
4209                 correct = True;
4210         }
4211
4212         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4213
4214         /* Check cli_setpathinfo_ext() */
4215         /* Re-create the file. */
4216         status = cli_openx(cli, fname,
4217                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4218         if (!NT_STATUS_IS_OK(status)) {
4219                 printf("Failed to recreate %s (%s)\n",
4220                         fname, nt_errstr(status));
4221                 correct = false;
4222         }
4223         cli_close(cli, fnum);
4224
4225         status = cli_setpathinfo_ext(
4226                 cli,
4227                 fname,
4228                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4229                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4230                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4231                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4232                 FILE_ATTRIBUTE_SYSTEM |
4233                 FILE_ATTRIBUTE_HIDDEN |
4234                 FILE_ATTRIBUTE_READONLY);
4235         if (!NT_STATUS_IS_OK(status)) {
4236                 printf("cli_setpathinfo_ext failed with %s\n",
4237                         nt_errstr(status));
4238                 correct = false;
4239         }
4240
4241         /* Check attributes are correct. */
4242         correct = check_attributes(cli,
4243                         fname,
4244                         FILE_ATTRIBUTE_SYSTEM |
4245                         FILE_ATTRIBUTE_HIDDEN |
4246                         FILE_ATTRIBUTE_READONLY);
4247         if (correct == false) {
4248                 goto out;
4249         }
4250
4251         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4252         status = cli_setpathinfo_ext(
4253                 cli,
4254                 fname,
4255                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4256                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4257                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4258                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4259                 FILE_ATTRIBUTE_NORMAL);
4260         if (!NT_STATUS_IS_OK(status)) {
4261                 printf("cli_setpathinfo_ext failed with %s\n",
4262                         nt_errstr(status));
4263                 correct = false;
4264         }
4265
4266         /* Check attributes are correct. */
4267         correct = check_attributes(cli,
4268                         fname,
4269                         FILE_ATTRIBUTE_SYSTEM |
4270                         FILE_ATTRIBUTE_HIDDEN |
4271                         FILE_ATTRIBUTE_READONLY);
4272         if (correct == false) {
4273                 goto out;
4274         }
4275
4276         /* Setting to (uint16_t)-1 should also be ignored. */
4277         status = cli_setpathinfo_ext(
4278                 cli,
4279                 fname,
4280                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4281                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4282                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4283                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4284                 (uint32_t)-1);
4285         if (!NT_STATUS_IS_OK(status)) {
4286                 printf("cli_setpathinfo_ext failed with %s\n",
4287                         nt_errstr(status));
4288                 correct = false;
4289         }
4290
4291         /* Check attributes are correct. */
4292         correct = check_attributes(cli,
4293                         fname,
4294                         FILE_ATTRIBUTE_SYSTEM |
4295                         FILE_ATTRIBUTE_HIDDEN |
4296                         FILE_ATTRIBUTE_READONLY);
4297         if (correct == false) {
4298                 goto out;
4299         }
4300
4301         /* Setting to 0 should clear them all. */
4302         status = cli_setpathinfo_ext(
4303                 cli,
4304                 fname,
4305                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4306                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4307                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4308                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4309                 0);
4310         if (!NT_STATUS_IS_OK(status)) {
4311                 printf("cli_setpathinfo_ext failed with %s\n",
4312                         nt_errstr(status));
4313                 correct = false;
4314         }
4315
4316         /* Check attributes are correct. */
4317         correct = check_attributes(cli,
4318                         fname,
4319                         FILE_ATTRIBUTE_NORMAL);
4320         if (correct == false) {
4321                 goto out;
4322         }
4323
4324   out:
4325
4326         cli_unlink(cli,
4327                 fname,
4328                 FILE_ATTRIBUTE_SYSTEM |
4329                 FILE_ATTRIBUTE_HIDDEN|
4330                 FILE_ATTRIBUTE_READONLY);
4331
4332         if (!torture_close_connection(cli)) {
4333                 correct = False;
4334         }
4335
4336         printf("attrib test finished\n");
4337
4338         return correct;
4339 }
4340
4341 static NTSTATUS cli_qfilename(
4342         struct cli_state *cli,
4343         uint16_t fnum,
4344         TALLOC_CTX *mem_ctx,
4345         char **_name)
4346 {
4347         uint16_t recv_flags2;
4348         uint8_t *rdata;
4349         uint32_t num_rdata;
4350         NTSTATUS status;
4351         char *name = NULL;
4352         uint32_t namelen;
4353
4354         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4355                                SMB_QUERY_FILE_NAME_INFO,
4356                                4, CLI_BUFFER_SIZE, &recv_flags2,
4357                                &rdata, &num_rdata);
4358         if (!NT_STATUS_IS_OK(status)) {
4359                 return status;
4360         }
4361
4362         namelen = IVAL(rdata, 0);
4363         if (namelen > (num_rdata - 4)) {
4364                 TALLOC_FREE(rdata);
4365                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4366         }
4367
4368         pull_string_talloc(mem_ctx,
4369                            (const char *)rdata,
4370                            recv_flags2,
4371                            &name,
4372                            rdata + 4,
4373                            namelen,
4374                            STR_UNICODE);
4375         if (name == NULL) {
4376                 status = map_nt_error_from_unix(errno);
4377                 TALLOC_FREE(rdata);
4378                 return status;
4379         }
4380
4381         *_name = name;
4382         TALLOC_FREE(rdata);
4383         return NT_STATUS_OK;
4384 }
4385
4386 /*
4387   This checks a couple of trans2 calls
4388 */
4389 static bool run_trans2test(int dummy)
4390 {
4391         struct cli_state *cli;
4392         uint16_t fnum;
4393         off_t size;
4394         time_t c_time, a_time, m_time;
4395         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4396         const char *fname = "\\trans2.tst";
4397         const char *dname = "\\trans2";
4398         const char *fname2 = "\\trans2\\trans2.tst";
4399         char *pname = NULL;
4400         bool correct = True;
4401         NTSTATUS status;
4402         uint32_t fs_attr;
4403         uint64_t ino;
4404
4405         printf("starting trans2 test\n");
4406
4407         if (!torture_open_connection(&cli, 0)) {
4408                 return False;
4409         }
4410
4411         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4412                 /* Ensure ino is zero, SMB2 gets a real one. */
4413                 ino = 0;
4414         } else {
4415                 /* Ensure ino is -1, SMB1 never gets a real one. */
4416                 ino = (uint64_t)-1;
4417         }
4418
4419         status = cli_get_fs_attr_info(cli, &fs_attr);
4420         if (!NT_STATUS_IS_OK(status)) {
4421                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4422                        nt_errstr(status));
4423                 correct = false;
4424         }
4425
4426         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4427         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4428         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4429                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4430         if (!NT_STATUS_IS_OK(status)) {
4431                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4432                 correct = False;
4433         }
4434
4435         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4436         if (!NT_STATUS_IS_OK(status)) {
4437                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4438                 correct = False;
4439         }
4440         else if (strcmp(pname, fname)) {
4441                 printf("qfilename gave different name? [%s] [%s]\n",
4442                        fname, pname);
4443                 correct = False;
4444         }
4445
4446         cli_close(cli, fnum);
4447
4448         sleep(2);
4449
4450         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4451         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4452                           &fnum);
4453         if (!NT_STATUS_IS_OK(status)) {
4454                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4455                 return False;
4456         }
4457         cli_close(cli, fnum);
4458
4459         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4460                                 NULL);
4461         if (!NT_STATUS_IS_OK(status)) {
4462                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4463                 correct = False;
4464         } else {
4465                 time_t t = time(NULL);
4466
4467                 if (c_time != m_time) {
4468                         printf("create time=%s", ctime(&c_time));
4469                         printf("modify time=%s", ctime(&m_time));
4470                         printf("This system appears to have sticky create times\n");
4471                 }
4472                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4473                         printf("access time=%s", ctime(&a_time));
4474                         printf("This system appears to set a midnight access time\n");
4475                         correct = False;
4476                 }
4477
4478                 if (labs(m_time - t) > 60*60*24*7) {
4479                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4480                         correct = False;
4481                 }
4482         }
4483
4484
4485         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4486         cli_openx(cli, fname, 
4487                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4488         cli_close(cli, fnum);
4489         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4490                                 &m_time_ts, &size, NULL, &ino);
4491         if (!NT_STATUS_IS_OK(status)) {
4492                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4493                 correct = False;
4494         } else {
4495                 if (w_time_ts.tv_sec < 60*60*24*2) {
4496                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4497                         printf("This system appears to set a initial 0 write time\n");
4498                         correct = False;
4499                 }
4500                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4501                         /* SMB2 should always return an inode. */
4502                         if (ino == 0) {
4503                                 printf("SMB2 bad inode (0)\n");
4504                                 correct = false;
4505                         }
4506                 } else {
4507                         /* SMB1 must always return zero here. */
4508                         if (ino != 0) {
4509                                 printf("SMB1 bad inode (!0)\n");
4510                                 correct = false;
4511                         }
4512                 }
4513         }
4514
4515         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4516
4517
4518         /* check if the server updates the directory modification time
4519            when creating a new file */
4520         status = cli_mkdir(cli, dname);
4521         if (!NT_STATUS_IS_OK(status)) {
4522                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4523                 correct = False;
4524         }
4525         sleep(3);
4526         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4527                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4528         if (!NT_STATUS_IS_OK(status)) {
4529                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4530                 correct = False;
4531         }
4532
4533         cli_openx(cli, fname2, 
4534                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4535         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4536         cli_close(cli, fnum);
4537         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4538                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4539         if (!NT_STATUS_IS_OK(status)) {
4540                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4541                 correct = False;
4542         } else {
4543                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4544                     == 0) {
4545                         printf("This system does not update directory modification times\n");
4546                         correct = False;
4547                 }
4548         }
4549         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4550         cli_rmdir(cli, dname);
4551
4552         if (!torture_close_connection(cli)) {
4553                 correct = False;
4554         }
4555
4556         printf("trans2 test finished\n");
4557
4558         return correct;
4559 }
4560
4561 /*
4562   This checks new W2K calls.
4563 */
4564
4565 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4566 {
4567         uint8_t *buf = NULL;
4568         uint32_t len;
4569         NTSTATUS status;
4570
4571         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4572                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4573         if (!NT_STATUS_IS_OK(status)) {
4574                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4575                        nt_errstr(status));
4576         } else {
4577                 printf("qfileinfo: level %d, len = %u\n", level, len);
4578                 dump_data(0, (uint8_t *)buf, len);
4579                 printf("\n");
4580         }
4581         TALLOC_FREE(buf);
4582         return status;
4583 }
4584
4585 static bool run_w2ktest(int dummy)
4586 {
4587         struct cli_state *cli;
4588         uint16_t fnum;
4589         const char *fname = "\\w2ktest\\w2k.tst";
4590         int level;
4591         bool correct = True;
4592
4593         printf("starting w2k test\n");
4594
4595         if (!torture_open_connection(&cli, 0)) {
4596                 return False;
4597         }
4598
4599         cli_openx(cli, fname, 
4600                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4601
4602         for (level = 1004; level < 1040; level++) {
4603                 new_trans(cli, fnum, level);
4604         }
4605
4606         cli_close(cli, fnum);
4607
4608         if (!torture_close_connection(cli)) {
4609                 correct = False;
4610         }
4611
4612         printf("w2k test finished\n");
4613
4614         return correct;
4615 }
4616
4617
4618 /*
4619   this is a harness for some oplock tests
4620  */
4621 static bool run_oplock1(int dummy)
4622 {
4623         struct cli_state *cli1;
4624         const char *fname = "\\lockt1.lck";
4625         uint16_t fnum1;
4626         bool correct = True;
4627         NTSTATUS status;
4628
4629         printf("starting oplock test 1\n");
4630
4631         if (!torture_open_connection(&cli1, 0)) {
4632                 return False;
4633         }
4634
4635         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4636
4637         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4638
4639         cli1->use_oplocks = True;
4640
4641         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4642                           &fnum1);
4643         if (!NT_STATUS_IS_OK(status)) {
4644                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4645                 return False;
4646         }
4647
4648         cli1->use_oplocks = False;
4649
4650         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4651         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4652
4653         status = cli_close(cli1, fnum1);
4654         if (!NT_STATUS_IS_OK(status)) {
4655                 printf("close2 failed (%s)\n", nt_errstr(status));
4656                 return False;
4657         }
4658
4659         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4660         if (!NT_STATUS_IS_OK(status)) {
4661                 printf("unlink failed (%s)\n", nt_errstr(status));
4662                 return False;
4663         }
4664
4665         if (!torture_close_connection(cli1)) {
4666                 correct = False;
4667         }
4668
4669         printf("finished oplock test 1\n");
4670
4671         return correct;
4672 }
4673
4674 static bool run_oplock2(int dummy)
4675 {
4676         struct cli_state *cli1, *cli2;
4677         const char *fname = "\\lockt2.lck";
4678         uint16_t fnum1, fnum2;
4679         int saved_use_oplocks = use_oplocks;
4680         char buf[4];
4681         bool correct = True;
4682         volatile bool *shared_correct;
4683         size_t nread;
4684         NTSTATUS status;
4685
4686         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4687         *shared_correct = True;
4688
4689         use_level_II_oplocks = True;
4690         use_oplocks = True;
4691
4692         printf("starting oplock test 2\n");
4693
4694         if (!torture_open_connection(&cli1, 0)) {
4695                 use_level_II_oplocks = False;
4696                 use_oplocks = saved_use_oplocks;
4697                 return False;
4698         }
4699
4700         if (!torture_open_connection(&cli2, 1)) {
4701                 use_level_II_oplocks = False;
4702                 use_oplocks = saved_use_oplocks;
4703                 return False;
4704         }
4705
4706         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4707
4708         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4709         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4710
4711         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4712                           &fnum1);
4713         if (!NT_STATUS_IS_OK(status)) {
4714                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4715                 return False;
4716         }
4717
4718         /* Don't need the globals any more. */
4719         use_level_II_oplocks = False;
4720         use_oplocks = saved_use_oplocks;
4721
4722         if (fork() == 0) {
4723                 /* Child code */
4724                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4725                 if (!NT_STATUS_IS_OK(status)) {
4726                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4727                         *shared_correct = False;
4728                         exit(0);
4729                 }
4730
4731                 sleep(2);
4732
4733                 status = cli_close(cli2, fnum2);
4734                 if (!NT_STATUS_IS_OK(status)) {
4735                         printf("close2 failed (%s)\n", nt_errstr(status));
4736                         *shared_correct = False;
4737                 }
4738
4739                 exit(0);
4740         }
4741
4742         sleep(2);
4743
4744         /* Ensure cli1 processes the break. Empty file should always return 0
4745          * bytes.  */
4746         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4747         if (!NT_STATUS_IS_OK(status)) {
4748                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4749                 correct = false;
4750         } else if (nread != 0) {
4751                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4752                       (unsigned long)nread, 0);
4753                 correct = false;
4754         }
4755
4756         /* Should now be at level II. */
4757         /* Test if sending a write locks causes a break to none. */
4758         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4759         if (!NT_STATUS_IS_OK(status)) {
4760                 printf("lock failed (%s)\n", nt_errstr(status));
4761                 correct = False;
4762         }
4763
4764         cli_unlock(cli1, fnum1, 0, 4);
4765
4766         sleep(2);
4767
4768         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4769         if (!NT_STATUS_IS_OK(status)) {
4770                 printf("lock failed (%s)\n", nt_errstr(status));
4771                 correct = False;
4772         }
4773
4774         cli_unlock(cli1, fnum1, 0, 4);
4775
4776         sleep(2);
4777
4778         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4779
4780         status = cli_close(cli1, fnum1);
4781         if (!NT_STATUS_IS_OK(status)) {
4782                 printf("close1 failed (%s)\n", nt_errstr(status));
4783                 correct = False;
4784         }
4785
4786         sleep(4);
4787
4788         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4789         if (!NT_STATUS_IS_OK(status)) {
4790                 printf("unlink failed (%s)\n", nt_errstr(status));
4791                 correct = False;
4792         }
4793
4794         if (!torture_close_connection(cli1)) {
4795                 correct = False;
4796         }
4797
4798         if (!*shared_correct) {
4799                 correct = False;
4800         }
4801
4802         printf("finished oplock test 2\n");
4803
4804         return correct;
4805 }
4806
4807 struct oplock4_state {
4808         struct tevent_context *ev;
4809         struct cli_state *cli;
4810         bool *got_break;
4811         uint16_t *fnum2;
4812 };
4813
4814 static void oplock4_got_break(struct tevent_req *req);
4815 static void oplock4_got_open(struct tevent_req *req);
4816
4817 static bool run_oplock4(int dummy)
4818 {
4819         struct tevent_context *ev;
4820         struct cli_state *cli1, *cli2;
4821         struct tevent_req *oplock_req, *open_req;
4822         const char *fname = "\\lockt4.lck";
4823         const char *fname_ln = "\\lockt4_ln.lck";
4824         uint16_t fnum1, fnum2;
4825         int saved_use_oplocks = use_oplocks;
4826         NTSTATUS status;
4827         bool correct = true;
4828
4829         bool got_break;
4830
4831         struct oplock4_state *state;
4832
4833         printf("starting oplock test 4\n");
4834
4835         if (!torture_open_connection(&cli1, 0)) {
4836                 use_level_II_oplocks = false;
4837                 use_oplocks = saved_use_oplocks;
4838                 return false;
4839         }
4840
4841         if (!torture_open_connection(&cli2, 1)) {
4842                 use_level_II_oplocks = false;
4843                 use_oplocks = saved_use_oplocks;
4844                 return false;
4845         }
4846
4847         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4848         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4849
4850         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4851         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4852
4853         /* Create the file. */
4854         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4855                           &fnum1);
4856         if (!NT_STATUS_IS_OK(status)) {
4857                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4858                 return false;
4859         }
4860
4861         status = cli_close(cli1, fnum1);
4862         if (!NT_STATUS_IS_OK(status)) {
4863                 printf("close1 failed (%s)\n", nt_errstr(status));
4864                 return false;
4865         }
4866
4867         /* Now create a hardlink. */
4868         status = cli_hardlink(cli1, fname, fname_ln);
4869         if (!NT_STATUS_IS_OK(status)) {
4870                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4871                 return false;
4872         }
4873
4874         /* Prove that opening hardlinks cause deny modes to conflict. */
4875         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4876         if (!NT_STATUS_IS_OK(status)) {
4877                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4878                 return false;
4879         }
4880
4881         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4882         if (NT_STATUS_IS_OK(status)) {
4883                 printf("open of %s succeeded - should fail with sharing violation.\n",
4884                         fname_ln);
4885                 return false;
4886         }
4887
4888         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4889                 printf("open of %s should fail with sharing violation. Got %s\n",
4890                         fname_ln, nt_errstr(status));
4891                 return false;
4892         }
4893
4894         status = cli_close(cli1, fnum1);
4895         if (!NT_STATUS_IS_OK(status)) {
4896                 printf("close1 failed (%s)\n", nt_errstr(status));
4897                 return false;
4898         }
4899
4900         cli1->use_oplocks = true;
4901         cli2->use_oplocks = true;
4902
4903         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4904         if (!NT_STATUS_IS_OK(status)) {
4905                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4906                 return false;
4907         }
4908
4909         ev = samba_tevent_context_init(talloc_tos());
4910         if (ev == NULL) {
4911                 printf("tevent_context_init failed\n");
4912                 return false;
4913         }
4914
4915         state = talloc(ev, struct oplock4_state);
4916         if (state == NULL) {
4917                 printf("talloc failed\n");
4918                 return false;
4919         }
4920         state->ev = ev;
4921         state->cli = cli1;
4922         state->got_break = &got_break;
4923         state->fnum2 = &fnum2;
4924
4925         oplock_req = cli_smb_oplock_break_waiter_send(
4926                 talloc_tos(), ev, cli1);
4927         if (oplock_req == NULL) {
4928                 printf("cli_smb_oplock_break_waiter_send failed\n");
4929                 return false;
4930         }
4931         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4932
4933         open_req = cli_openx_send(
4934                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4935         if (open_req == NULL) {
4936                 printf("cli_openx_send failed\n");
4937                 return false;
4938         }
4939         tevent_req_set_callback(open_req, oplock4_got_open, state);
4940
4941         got_break = false;
4942         fnum2 = 0xffff;
4943
4944         while (!got_break || fnum2 == 0xffff) {
4945                 int ret;
4946                 ret = tevent_loop_once(ev);
4947                 if (ret == -1) {
4948                         printf("tevent_loop_once failed: %s\n",
4949                                strerror(errno));
4950                         return false;
4951                 }
4952         }
4953
4954         status = cli_close(cli2, fnum2);
4955         if (!NT_STATUS_IS_OK(status)) {
4956                 printf("close2 failed (%s)\n", nt_errstr(status));
4957                 correct = false;
4958         }
4959
4960         status = cli_close(cli1, fnum1);
4961         if (!NT_STATUS_IS_OK(status)) {
4962                 printf("close1 failed (%s)\n", nt_errstr(status));
4963                 correct = false;
4964         }
4965
4966         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4967         if (!NT_STATUS_IS_OK(status)) {
4968                 printf("unlink failed (%s)\n", nt_errstr(status));
4969                 correct = false;
4970         }
4971
4972         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4973         if (!NT_STATUS_IS_OK(status)) {
4974                 printf("unlink failed (%s)\n", nt_errstr(status));
4975                 correct = false;
4976         }
4977
4978         if (!torture_close_connection(cli1)) {
4979                 correct = false;
4980         }
4981
4982         if (!got_break) {
4983                 correct = false;
4984         }
4985
4986         printf("finished oplock test 4\n");
4987
4988         return correct;
4989 }
4990
4991 static void oplock4_got_break(struct tevent_req *req)
4992 {
4993         struct oplock4_state *state = tevent_req_callback_data(
4994                 req, struct oplock4_state);
4995         uint16_t fnum;
4996         uint8_t level;
4997         NTSTATUS status;
4998
4999         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5000         TALLOC_FREE(req);
5001         if (!NT_STATUS_IS_OK(status)) {
5002                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5003                        nt_errstr(status));
5004                 return;
5005         }
5006         *state->got_break = true;
5007
5008         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5009                                   NO_OPLOCK);
5010         if (req == NULL) {
5011                 printf("cli_oplock_ack_send failed\n");
5012                 return;
5013         }
5014 }
5015
5016 static void oplock4_got_open(struct tevent_req *req)
5017 {
5018         struct oplock4_state *state = tevent_req_callback_data(
5019                 req, struct oplock4_state);
5020         NTSTATUS status;
5021
5022         status = cli_openx_recv(req, state->fnum2);
5023         if (!NT_STATUS_IS_OK(status)) {
5024                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5025                 *state->fnum2 = 0xffff;
5026         }
5027 }
5028
5029 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5030
5031 struct oplock5_state {
5032         int pipe_down_fd;
5033 };
5034
5035 /*
5036  * Async open the file that has a kernel oplock, do an echo to get
5037  * that 100% across, close the file to signal to the child fd that the
5038  * oplock can be dropped, wait for the open reply.
5039  */
5040
5041 static void oplock5_opened(struct tevent_req *subreq);
5042 static void oplock5_pong(struct tevent_req *subreq);
5043 static void oplock5_timedout(struct tevent_req *subreq);
5044
5045 static struct tevent_req *oplock5_send(
5046         TALLOC_CTX *mem_ctx,
5047         struct tevent_context *ev,
5048         struct cli_state *cli,
5049         const char *fname,
5050         int pipe_down_fd)
5051 {
5052         struct tevent_req *req = NULL, *subreq = NULL;
5053         struct oplock5_state *state = NULL;
5054         static uint8_t data = 0;
5055
5056         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5057         if (req == NULL) {
5058                 return NULL;
5059         }
5060         state->pipe_down_fd = pipe_down_fd;
5061
5062         subreq = cli_ntcreate_send(
5063                 state,
5064                 ev,
5065                 cli,
5066                 fname,
5067                 0,                      /* CreatFlags */
5068                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5069                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5070                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5071                 FILE_OPEN,               /* CreateDisposition */
5072                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5073                 0,                       /* Impersonation */
5074                 0);                      /* SecurityFlags */
5075         if (tevent_req_nomem(subreq, req)) {
5076                 return tevent_req_post(req, ev);
5077         }
5078         tevent_req_set_callback(subreq, oplock5_opened, req);
5079
5080         subreq = cli_echo_send(
5081                 state,
5082                 ev,
5083                 cli,
5084                 1,
5085                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5086         if (tevent_req_nomem(subreq, req)) {
5087                 return tevent_req_post(req, ev);
5088         }
5089         tevent_req_set_callback(subreq, oplock5_pong, req);
5090
5091         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5092         if (tevent_req_nomem(subreq, req)) {
5093                 return tevent_req_post(req, ev);
5094         }
5095         tevent_req_set_callback(subreq, oplock5_timedout, req);
5096
5097         return req;
5098 }
5099
5100 static void oplock5_opened(struct tevent_req *subreq)
5101 {
5102         struct tevent_req *req = tevent_req_callback_data(
5103                 subreq, struct tevent_req);
5104         NTSTATUS status;
5105         uint16_t fnum;
5106
5107         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5108         TALLOC_FREE(subreq);
5109         if (tevent_req_nterror(req, status)) {
5110                 return;
5111         }
5112         tevent_req_done(req);
5113 }
5114
5115 static void oplock5_pong(struct tevent_req *subreq)
5116 {
5117         struct tevent_req *req = tevent_req_callback_data(
5118                 subreq, struct tevent_req);
5119         struct oplock5_state *state = tevent_req_data(
5120                 req, struct oplock5_state);
5121         NTSTATUS status;
5122
5123         status = cli_echo_recv(subreq);
5124         TALLOC_FREE(subreq);
5125         if (tevent_req_nterror(req, status)) {
5126                 return;
5127         }
5128
5129         close(state->pipe_down_fd);
5130 }
5131
5132 static void oplock5_timedout(struct tevent_req *subreq)
5133 {
5134         struct tevent_req *req = tevent_req_callback_data(
5135                 subreq, struct tevent_req);
5136         bool ok;
5137
5138         ok = tevent_wakeup_recv(subreq);
5139         TALLOC_FREE(subreq);
5140         if (!ok) {
5141                 tevent_req_oom(req);
5142                 return;
5143         }
5144         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5145 }
5146
5147 static NTSTATUS oplock5_recv(struct tevent_req *req)
5148 {
5149         return tevent_req_simple_recv_ntstatus(req);
5150 }
5151
5152 static bool run_oplock5(int dummy)
5153 {
5154         struct tevent_context *ev = NULL;
5155         struct tevent_req *req = NULL;
5156         struct cli_state *cli = NULL;
5157         const char *fname = "oplock5.txt";
5158         int pipe_down[2], pipe_up[2];
5159         pid_t child_pid;
5160         uint8_t c = '\0';
5161         NTSTATUS status;
5162         int ret;
5163         bool ok;
5164
5165         printf("starting oplock5\n");
5166
5167         if (local_path == NULL) {
5168                 d_fprintf(stderr, "oplock5 must be given a local path via "
5169                           "-l <localpath>\n");
5170                 return false;
5171         }
5172
5173         ret = pipe(pipe_down);
5174         if (ret == -1) {
5175                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5176                 return false;
5177         }
5178         ret = pipe(pipe_up);
5179         if (ret == -1) {
5180                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5181                 return false;
5182         }
5183
5184         child_pid = fork();
5185         if (child_pid == -1) {
5186                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5187                 return false;
5188         }
5189
5190         if (child_pid == 0) {
5191                 char *local_file = NULL;
5192                 int fd;
5193
5194                 close(pipe_down[1]);
5195                 close(pipe_up[0]);
5196
5197                 local_file = talloc_asprintf(
5198                         talloc_tos(), "%s/%s", local_path, fname);
5199                 if (local_file == 0) {
5200                         c = 1;
5201                         goto do_write;
5202                 }
5203                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5204                 if (fd == -1) {
5205                         d_fprintf(stderr,
5206                                   "open(%s) in child failed: %s\n",
5207                                   local_file,
5208                                   strerror(errno));
5209                         c = 2;
5210                         goto do_write;
5211                 }
5212
5213                 signal(SIGIO, SIG_IGN);
5214
5215                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5216                 if (ret == -1) {
5217                         d_fprintf(stderr,
5218                                   "SETLEASE in child failed: %s\n",
5219                                   strerror(errno));
5220                         c = 3;
5221                         goto do_write;
5222                 }
5223
5224         do_write:
5225                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5226                 if (ret == -1) {
5227                         d_fprintf(stderr,
5228                                   "sys_write failed: %s\n",
5229                                   strerror(errno));
5230                         exit(4);
5231                 }
5232                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5233                 if (ret == -1) {
5234                         d_fprintf(stderr,
5235                                   "sys_read failed: %s\n",
5236                                   strerror(errno));
5237                         exit(5);
5238                 }
5239                 exit(0);
5240         }
5241
5242         close(pipe_up[1]);
5243         close(pipe_down[0]);
5244
5245         ret = sys_read(pipe_up[0], &c, sizeof(c));
5246         if (ret != 1) {
5247                 d_fprintf(stderr,
5248                           "sys_read failed: %s\n",
5249                           strerror(errno));
5250                 return false;
5251         }
5252         if (c != 0) {
5253                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5254                 return false;
5255         }
5256
5257         ok = torture_open_connection(&cli, 0);
5258         if (!ok) {
5259                 d_fprintf(stderr, "torture_open_connection failed\n");
5260                 return false;
5261         }
5262
5263         ev = samba_tevent_context_init(talloc_tos());
5264         if (ev == NULL) {
5265                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5266                 return false;
5267         }
5268
5269         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5270         if (req == NULL) {
5271                 d_fprintf(stderr, "oplock5_send failed\n");
5272                 return false;
5273         }
5274
5275         ok = tevent_req_poll_ntstatus(req, ev, &status);
5276         if (!ok) {
5277                 d_fprintf(stderr,
5278                           "tevent_req_poll_ntstatus failed: %s\n",
5279                           nt_errstr(status));
5280                 return false;
5281         }
5282
5283         status = oplock5_recv(req);
5284         TALLOC_FREE(req);
5285         if (!NT_STATUS_IS_OK(status)) {
5286                 d_fprintf(stderr,
5287                           "oplock5 failed: %s\n",
5288                           nt_errstr(status));
5289                 return false;
5290         }
5291
5292         return true;
5293 }
5294
5295 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5296
5297 /*
5298   Test delete on close semantics.
5299  */
5300 static bool run_deletetest(int dummy)
5301 {
5302         struct cli_state *cli1 = NULL;
5303         struct cli_state *cli2 = NULL;
5304         const char *fname = "\\delete.file";
5305         uint16_t fnum1 = (uint16_t)-1;
5306         uint16_t fnum2 = (uint16_t)-1;
5307         bool correct = false;
5308         NTSTATUS status;
5309
5310         printf("starting delete test\n");
5311
5312         if (!torture_open_connection(&cli1, 0)) {
5313                 return False;
5314         }
5315
5316         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5317
5318         /* Test 1 - this should delete the file on close. */
5319
5320         cli_setatr(cli1, fname, 0, 0);
5321         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5322
5323         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5324                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5325                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5326         if (!NT_STATUS_IS_OK(status)) {
5327                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5328                 goto fail;
5329         }
5330
5331         status = cli_close(cli1, fnum1);
5332         if (!NT_STATUS_IS_OK(status)) {
5333                 printf("[1] close failed (%s)\n", nt_errstr(status));
5334                 goto fail;
5335         }
5336
5337         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5338         if (NT_STATUS_IS_OK(status)) {
5339                 printf("[1] open of %s succeeded (should fail)\n", fname);
5340                 goto fail;
5341         }
5342
5343         printf("first delete on close test succeeded.\n");
5344
5345         /* Test 2 - this should delete the file on close. */
5346
5347         cli_setatr(cli1, fname, 0, 0);
5348         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5349
5350         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5351                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5352                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5353         if (!NT_STATUS_IS_OK(status)) {
5354                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5355                 goto fail;
5356         }
5357
5358         status = cli_nt_delete_on_close(cli1, fnum1, true);
5359         if (!NT_STATUS_IS_OK(status)) {
5360                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5361                 goto fail;
5362         }
5363
5364         status = cli_close(cli1, fnum1);
5365         if (!NT_STATUS_IS_OK(status)) {
5366                 printf("[2] close failed (%s)\n", nt_errstr(status));
5367                 goto fail;
5368         }
5369
5370         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5371         if (NT_STATUS_IS_OK(status)) {
5372                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5373                 status = cli_close(cli1, fnum1);
5374                 if (!NT_STATUS_IS_OK(status)) {
5375                         printf("[2] close failed (%s)\n", nt_errstr(status));
5376                 }
5377                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5378                 goto fail;
5379         }
5380
5381         printf("second delete on close test succeeded.\n");
5382
5383         /* Test 3 - ... */
5384         cli_setatr(cli1, fname, 0, 0);
5385         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5386
5387         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5388                               FILE_ATTRIBUTE_NORMAL,
5389                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5390                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5391         if (!NT_STATUS_IS_OK(status)) {
5392                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5393                 goto fail;
5394         }
5395
5396         /* This should fail with a sharing violation - open for delete is only compatible
5397            with SHARE_DELETE. */
5398
5399         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5400                               FILE_ATTRIBUTE_NORMAL,
5401                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5402                               FILE_OPEN, 0, 0, &fnum2, NULL);
5403         if (NT_STATUS_IS_OK(status)) {
5404                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5405                 goto fail;
5406         }
5407
5408         /* This should succeed. */
5409         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5410                              FILE_ATTRIBUTE_NORMAL,
5411                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5412                              FILE_OPEN, 0, 0, &fnum2, NULL);
5413         if (!NT_STATUS_IS_OK(status)) {
5414                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5415                 goto fail;
5416         }
5417
5418         status = cli_nt_delete_on_close(cli1, fnum1, true);
5419         if (!NT_STATUS_IS_OK(status)) {
5420                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5421                 goto fail;
5422         }
5423
5424         status = cli_close(cli1, fnum1);
5425         if (!NT_STATUS_IS_OK(status)) {
5426                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5427                 goto fail;
5428         }
5429
5430         status = cli_close(cli1, fnum2);
5431         if (!NT_STATUS_IS_OK(status)) {
5432                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5433                 goto fail;
5434         }
5435
5436         /* This should fail - file should no longer be there. */
5437
5438         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5439         if (NT_STATUS_IS_OK(status)) {
5440                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5441                 status = cli_close(cli1, fnum1);
5442                 if (!NT_STATUS_IS_OK(status)) {
5443                         printf("[3] close failed (%s)\n", nt_errstr(status));
5444                 }
5445                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5446                 goto fail;
5447         }
5448
5449         printf("third delete on close test succeeded.\n");
5450
5451         /* Test 4 ... */
5452         cli_setatr(cli1, fname, 0, 0);
5453         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5454
5455         status = cli_ntcreate(cli1, fname, 0,
5456                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5457                               FILE_ATTRIBUTE_NORMAL,
5458                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5459                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5460         if (!NT_STATUS_IS_OK(status)) {
5461                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5462                 goto fail;
5463         }
5464
5465         /* This should succeed. */
5466         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5467                              FILE_ATTRIBUTE_NORMAL,
5468                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5469                              FILE_OPEN, 0, 0, &fnum2, NULL);
5470         if (!NT_STATUS_IS_OK(status)) {
5471                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5472                 goto fail;
5473         }
5474
5475         status = cli_close(cli1, fnum2);
5476         if (!NT_STATUS_IS_OK(status)) {
5477                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5478                 goto fail;
5479         }
5480
5481         status = cli_nt_delete_on_close(cli1, fnum1, true);
5482         if (!NT_STATUS_IS_OK(status)) {
5483                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5484                 goto fail;
5485         }
5486
5487         /* This should fail - no more opens once delete on close set. */
5488         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5489                               FILE_ATTRIBUTE_NORMAL,
5490                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5491                               FILE_OPEN, 0, 0, &fnum2, NULL);
5492         if (NT_STATUS_IS_OK(status)) {
5493                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5494                 goto fail;
5495         }
5496
5497         status = cli_close(cli1, fnum1);
5498         if (!NT_STATUS_IS_OK(status)) {
5499                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5500                 goto fail;
5501         }
5502
5503         printf("fourth delete on close test succeeded.\n");
5504
5505         /* Test 5 ... */
5506         cli_setatr(cli1, fname, 0, 0);
5507         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5508
5509         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5510         if (!NT_STATUS_IS_OK(status)) {
5511                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5512                 goto fail;
5513         }
5514
5515         /* This should fail - only allowed on NT opens with DELETE access. */
5516
5517         status = cli_nt_delete_on_close(cli1, fnum1, true);
5518         if (NT_STATUS_IS_OK(status)) {
5519                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5520                 goto fail;
5521         }
5522
5523         status = cli_close(cli1, fnum1);
5524         if (!NT_STATUS_IS_OK(status)) {
5525                 printf("[5] close failed (%s)\n", nt_errstr(status));
5526                 goto fail;
5527         }
5528
5529         printf("fifth delete on close test succeeded.\n");
5530
5531         /* Test 6 ... */
5532         cli_setatr(cli1, fname, 0, 0);
5533         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5534
5535         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5536                              FILE_ATTRIBUTE_NORMAL,
5537                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5538                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5539         if (!NT_STATUS_IS_OK(status)) {
5540                 printf("[6] open of %s failed (%s)\n", fname,
5541                        nt_errstr(status));
5542                 goto fail;
5543         }
5544
5545         /* This should fail - only allowed on NT opens with DELETE access. */
5546
5547         status = cli_nt_delete_on_close(cli1, fnum1, true);
5548         if (NT_STATUS_IS_OK(status)) {
5549                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5550                 goto fail;
5551         }
5552
5553         status = cli_close(cli1, fnum1);
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 printf("[6] close failed (%s)\n", nt_errstr(status));
5556                 goto fail;
5557         }
5558
5559         printf("sixth delete on close test succeeded.\n");
5560
5561         /* Test 7 ... */
5562         cli_setatr(cli1, fname, 0, 0);
5563         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5564
5565         status = cli_ntcreate(cli1, fname, 0,
5566                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5567                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5568                               0, 0, &fnum1, NULL);
5569         if (!NT_STATUS_IS_OK(status)) {
5570                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5571                 goto fail;
5572         }
5573
5574         status = cli_nt_delete_on_close(cli1, fnum1, true);
5575         if (!NT_STATUS_IS_OK(status)) {
5576                 printf("[7] setting delete_on_close on file failed !\n");
5577                 goto fail;
5578         }
5579
5580         status = cli_nt_delete_on_close(cli1, fnum1, false);
5581         if (!NT_STATUS_IS_OK(status)) {
5582                 printf("[7] unsetting delete_on_close on file failed !\n");
5583                 goto fail;
5584         }
5585
5586         status = cli_close(cli1, fnum1);
5587         if (!NT_STATUS_IS_OK(status)) {
5588                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5589                 goto fail;
5590         }
5591
5592         /* This next open should succeed - we reset the flag. */
5593         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5594         if (!NT_STATUS_IS_OK(status)) {
5595                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5596                 goto fail;
5597         }
5598
5599         status = cli_close(cli1, fnum1);
5600         if (!NT_STATUS_IS_OK(status)) {
5601                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5602                 goto fail;
5603         }
5604
5605         printf("seventh delete on close test succeeded.\n");
5606
5607         /* Test 8 ... */
5608         cli_setatr(cli1, fname, 0, 0);
5609         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5610
5611         if (!torture_open_connection(&cli2, 1)) {
5612                 printf("[8] failed to open second connection.\n");
5613                 goto fail;
5614         }
5615
5616         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5617
5618         status = cli_ntcreate(cli1, fname, 0,
5619                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5620                              FILE_ATTRIBUTE_NORMAL,
5621                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5622                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5623         if (!NT_STATUS_IS_OK(status)) {
5624                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5625                 goto fail;
5626         }
5627
5628         status = cli_ntcreate(cli2, fname, 0,
5629                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5630                              FILE_ATTRIBUTE_NORMAL,
5631                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5632                              FILE_OPEN, 0, 0, &fnum2, NULL);
5633         if (!NT_STATUS_IS_OK(status)) {
5634                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5635                 goto fail;
5636         }
5637
5638         status = cli_nt_delete_on_close(cli1, fnum1, true);
5639         if (!NT_STATUS_IS_OK(status)) {
5640                 printf("[8] setting delete_on_close on file failed !\n");
5641                 goto fail;
5642         }
5643
5644         status = cli_close(cli1, fnum1);
5645         if (!NT_STATUS_IS_OK(status)) {
5646                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5647                 goto fail;
5648         }
5649
5650         status = cli_close(cli2, fnum2);
5651         if (!NT_STATUS_IS_OK(status)) {
5652                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5653                 goto fail;
5654         }
5655
5656         /* This should fail.. */
5657         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5658         if (NT_STATUS_IS_OK(status)) {
5659                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5660                 goto fail;
5661         }
5662
5663         printf("eighth delete on close test succeeded.\n");
5664
5665         /* Test 9 ... */
5666
5667         /* This should fail - we need to set DELETE_ACCESS. */
5668         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5669                               FILE_ATTRIBUTE_NORMAL,
5670                               FILE_SHARE_NONE,
5671                               FILE_OVERWRITE_IF,
5672                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5673         if (NT_STATUS_IS_OK(status)) {
5674                 printf("[9] open of %s succeeded should have failed!\n", fname);
5675                 goto fail;
5676         }
5677
5678         printf("ninth delete on close test succeeded.\n");
5679
5680         /* Test 10 ... */
5681
5682         status = cli_ntcreate(cli1, fname, 0,
5683                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5684                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5685                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5686                              0, &fnum1, NULL);
5687         if (!NT_STATUS_IS_OK(status)) {
5688                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5689                 goto fail;
5690         }
5691
5692         /* This should delete the file. */
5693         status = cli_close(cli1, fnum1);
5694         if (!NT_STATUS_IS_OK(status)) {
5695                 printf("[10] close failed (%s)\n", nt_errstr(status));
5696                 goto fail;
5697         }
5698
5699         /* This should fail.. */
5700         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5701         if (NT_STATUS_IS_OK(status)) {
5702                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5703                 goto fail;
5704         }
5705
5706         printf("tenth delete on close test succeeded.\n");
5707
5708         /* Test 11 ... */
5709
5710         cli_setatr(cli1, fname, 0, 0);
5711         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5712
5713         /* Can we open a read-only file with delete access? */
5714
5715         /* Create a readonly file. */
5716         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5717                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5718                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5719         if (!NT_STATUS_IS_OK(status)) {
5720                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5721                 goto fail;
5722         }
5723
5724         status = cli_close(cli1, fnum1);
5725         if (!NT_STATUS_IS_OK(status)) {
5726                 printf("[11] close failed (%s)\n", nt_errstr(status));
5727                 goto fail;
5728         }
5729
5730         /* Now try open for delete access. */
5731         status = cli_ntcreate(cli1, fname, 0,
5732                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5733                              0,
5734                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5735                              FILE_OPEN, 0, 0, &fnum1, NULL);
5736         if (!NT_STATUS_IS_OK(status)) {
5737                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5738                 goto fail;
5739         }
5740
5741         cli_close(cli1, fnum1);
5742
5743         printf("eleventh delete on close test succeeded.\n");
5744
5745         /*
5746          * Test 12
5747          * like test 4 but with initial delete on close
5748          */
5749
5750         cli_setatr(cli1, fname, 0, 0);
5751         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5752
5753         status = cli_ntcreate(cli1, fname, 0,
5754                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5755                               FILE_ATTRIBUTE_NORMAL,
5756                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5757                               FILE_OVERWRITE_IF,
5758                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5759         if (!NT_STATUS_IS_OK(status)) {
5760                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5761                 goto fail;
5762         }
5763
5764         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5765                               FILE_ATTRIBUTE_NORMAL,
5766                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5767                               FILE_OPEN, 0, 0, &fnum2, NULL);
5768         if (!NT_STATUS_IS_OK(status)) {
5769                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5770                 goto fail;
5771         }
5772
5773         status = cli_close(cli1, fnum2);
5774         if (!NT_STATUS_IS_OK(status)) {
5775                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5776                 goto fail;
5777         }
5778
5779         status = cli_nt_delete_on_close(cli1, fnum1, true);
5780         if (!NT_STATUS_IS_OK(status)) {
5781                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5782                 goto fail;
5783         }
5784
5785         /* This should fail - no more opens once delete on close set. */
5786         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5787                               FILE_ATTRIBUTE_NORMAL,
5788                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5789                               FILE_OPEN, 0, 0, &fnum2, NULL);
5790         if (NT_STATUS_IS_OK(status)) {
5791                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5792                 goto fail;
5793         }
5794
5795         status = cli_nt_delete_on_close(cli1, fnum1, false);
5796         if (!NT_STATUS_IS_OK(status)) {
5797                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5798                 goto fail;
5799         }
5800
5801         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5802                               FILE_ATTRIBUTE_NORMAL,
5803                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5804                               FILE_OPEN, 0, 0, &fnum2, NULL);
5805         if (!NT_STATUS_IS_OK(status)) {
5806                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5807                 goto fail;
5808         }
5809
5810         status = cli_close(cli1, fnum2);
5811         if (!NT_STATUS_IS_OK(status)) {
5812                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5813                 goto fail;
5814         }
5815
5816         status = cli_close(cli1, fnum1);
5817         if (!NT_STATUS_IS_OK(status)) {
5818                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5819                 goto fail;
5820         }
5821
5822         /*
5823          * setting delete on close on the handle does
5824          * not unset the initial delete on close...
5825          */
5826         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5827                               FILE_ATTRIBUTE_NORMAL,
5828                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5829                               FILE_OPEN, 0, 0, &fnum2, NULL);
5830         if (NT_STATUS_IS_OK(status)) {
5831                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5832                 goto fail;
5833         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5834                 printf("ntcreate returned %s, expected "
5835                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5836                        nt_errstr(status));
5837                 goto fail;
5838         }
5839
5840         printf("twelfth delete on close test succeeded.\n");
5841
5842
5843         printf("finished delete test\n");
5844
5845         correct = true;
5846
5847   fail:
5848         /* FIXME: This will crash if we aborted before cli2 got
5849          * intialized, because these functions don't handle
5850          * uninitialized connections. */
5851
5852         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5853         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5854         cli_setatr(cli1, fname, 0, 0);
5855         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5856
5857         if (cli1 && !torture_close_connection(cli1)) {
5858                 correct = False;
5859         }
5860         if (cli2 && !torture_close_connection(cli2)) {
5861                 correct = False;
5862         }
5863         return correct;
5864 }
5865
5866 struct delete_stream_state {
5867         bool closed;
5868 };
5869
5870 static void delete_stream_unlinked(struct tevent_req *subreq);
5871 static void delete_stream_closed(struct tevent_req *subreq);
5872
5873 static struct tevent_req *delete_stream_send(
5874         TALLOC_CTX *mem_ctx,
5875         struct tevent_context *ev,
5876         struct cli_state *cli,
5877         const char *base_fname,
5878         uint16_t stream_fnum)
5879 {
5880         struct tevent_req *req = NULL, *subreq = NULL;
5881         struct delete_stream_state *state = NULL;
5882
5883         req = tevent_req_create(
5884                 mem_ctx, &state, struct delete_stream_state);
5885         if (req == NULL) {
5886                 return NULL;
5887         }
5888
5889         subreq = cli_unlink_send(
5890                 state,
5891                 ev,
5892                 cli,
5893                 base_fname,
5894                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5895         if (tevent_req_nomem(subreq, req)) {
5896                 return tevent_req_post(req, ev);
5897         }
5898         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5899
5900         subreq = cli_close_send(state, ev, cli, stream_fnum);
5901         if (tevent_req_nomem(subreq, req)) {
5902                 return tevent_req_post(req, ev);
5903         }
5904         tevent_req_set_callback(subreq, delete_stream_closed, req);
5905
5906         return req;
5907 }
5908
5909 static void delete_stream_unlinked(struct tevent_req *subreq)
5910 {
5911         struct tevent_req *req = tevent_req_callback_data(
5912                 subreq, struct tevent_req);
5913         struct delete_stream_state *state = tevent_req_data(
5914                 req, struct delete_stream_state);
5915         NTSTATUS status;
5916
5917         status = cli_unlink_recv(subreq);
5918         TALLOC_FREE(subreq);
5919         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5920                 printf("cli_unlink returned %s\n",
5921                        nt_errstr(status));
5922                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5923                 return;
5924         }
5925         if (!state->closed) {
5926                 /* close reply should have come in first */
5927                 printf("Not closed\n");
5928                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5929                 return;
5930         }
5931         tevent_req_done(req);
5932 }
5933
5934 static void delete_stream_closed(struct tevent_req *subreq)
5935 {
5936         struct tevent_req *req = tevent_req_callback_data(
5937                 subreq, struct tevent_req);
5938         struct delete_stream_state *state = tevent_req_data(
5939                 req, struct delete_stream_state);
5940         NTSTATUS status;
5941
5942         status = cli_close_recv(subreq);
5943         TALLOC_FREE(subreq);
5944         if (tevent_req_nterror(req, status)) {
5945                 return;
5946         }
5947         /* also waiting for the unlink to come back */
5948         state->closed = true;
5949 }
5950
5951 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5952 {
5953         return tevent_req_simple_recv_ntstatus(req);
5954 }
5955
5956 static bool run_delete_stream(int dummy)
5957 {
5958         struct tevent_context *ev = NULL;
5959         struct tevent_req *req = NULL;
5960         struct cli_state *cli = NULL;
5961         const char fname[] = "delete_stream";
5962         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5963         uint16_t fnum1, fnum2;
5964         NTSTATUS status;
5965         bool ok;
5966
5967         printf("Starting stream delete test\n");
5968
5969         ok = torture_open_connection(&cli, 0);
5970         if (!ok) {
5971                 return false;
5972         }
5973
5974         cli_setatr(cli, fname, 0, 0);
5975         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5976
5977         /* Create the file. */
5978         status = cli_ntcreate(
5979                 cli,
5980                 fname,
5981                 0,
5982                 READ_CONTROL_ACCESS,
5983                 0,
5984                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5985                 FILE_CREATE,
5986                 0x0,
5987                 0x0,
5988                 &fnum1,
5989                 NULL);
5990         if (!NT_STATUS_IS_OK(status)) {
5991                 d_fprintf(stderr,
5992                           "cli_ntcreate of %s failed (%s)\n",
5993                           fname,
5994                           nt_errstr(status));
5995                 return false;
5996         }
5997         status = cli_close(cli, fnum1);
5998         if (!NT_STATUS_IS_OK(status)) {
5999                 d_fprintf(stderr,
6000                           "cli_close of %s failed (%s)\n",
6001                           fname,
6002                           nt_errstr(status));
6003                 return false;
6004         }
6005
6006         /* Now create the stream. */
6007         status = cli_ntcreate(
6008                 cli,
6009                 fname_stream,
6010                 0,
6011                 FILE_WRITE_DATA,
6012                 0,
6013                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6014                 FILE_CREATE,
6015                 0x0,
6016                 0x0,
6017                 &fnum1,
6018                 NULL);
6019
6020         if (!NT_STATUS_IS_OK(status)) {
6021                 d_fprintf(stderr,
6022                           "cli_ntcreate of %s failed (%s)\n",
6023                           fname_stream,
6024                           nt_errstr(status));
6025                 return false;
6026         }
6027
6028         /* open it a second time */
6029
6030         status = cli_ntcreate(
6031                 cli,
6032                 fname_stream,
6033                 0,
6034                 FILE_WRITE_DATA,
6035                 0,
6036                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6037                 FILE_OPEN,
6038                 0x0,
6039                 0x0,
6040                 &fnum2,
6041                 NULL);
6042
6043         if (!NT_STATUS_IS_OK(status)) {
6044                 d_fprintf(stderr,
6045                           "2nd cli_ntcreate of %s failed (%s)\n",
6046                           fname_stream,
6047                           nt_errstr(status));
6048                 return false;
6049         }
6050
6051         ev = samba_tevent_context_init(talloc_tos());
6052         if (ev == NULL) {
6053                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6054                 return false;
6055         }
6056
6057         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6058         if (req == NULL) {
6059                 d_fprintf(stderr, "delete_stream_send failed\n");
6060                 return false;
6061         }
6062
6063         ok = tevent_req_poll_ntstatus(req, ev, &status);
6064         if (!ok) {
6065                 d_fprintf(stderr,
6066                           "tevent_req_poll_ntstatus failed: %s\n",
6067                           nt_errstr(status));
6068                 return false;
6069         }
6070
6071         status = delete_stream_recv(req);
6072         TALLOC_FREE(req);
6073         if (!NT_STATUS_IS_OK(status)) {
6074                 d_fprintf(stderr,
6075                           "delete_stream failed: %s\n",
6076                           nt_errstr(status));
6077                 return false;
6078         }
6079
6080         status = cli_close(cli, fnum2);
6081         if (!NT_STATUS_IS_OK(status)) {
6082                 d_fprintf(stderr,
6083                           "close failed: %s\n",
6084                           nt_errstr(status));
6085                 return false;
6086         }
6087
6088         status = cli_unlink(
6089                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6090         if (!NT_STATUS_IS_OK(status)) {
6091                 d_fprintf(stderr,
6092                           "unlink failed: %s\n",
6093                           nt_errstr(status));
6094                 return false;
6095         }
6096
6097         return true;
6098 }
6099
6100 /*
6101   Exercise delete on close semantics - use on the PRINT1 share in torture
6102   testing.
6103  */
6104 static bool run_delete_print_test(int dummy)
6105 {
6106         struct cli_state *cli1 = NULL;
6107         const char *fname = "print_delete.file";
6108         uint16_t fnum1 = (uint16_t)-1;
6109         bool correct = false;
6110         const char *buf = "print file data\n";
6111         NTSTATUS status;
6112
6113         printf("starting print delete test\n");
6114
6115         if (!torture_open_connection(&cli1, 0)) {
6116                 return false;
6117         }
6118
6119         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6120
6121         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6122                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6123                               0, 0, &fnum1, NULL);
6124         if (!NT_STATUS_IS_OK(status)) {
6125                 printf("open of %s failed (%s)\n",
6126                         fname,
6127                         nt_errstr(status));
6128                 goto fail;
6129         }
6130
6131         status = cli_writeall(cli1,
6132                         fnum1,
6133                         0,
6134                         (const uint8_t *)buf,
6135                         0, /* offset */
6136                         strlen(buf), /* size */
6137                         NULL);
6138         if (!NT_STATUS_IS_OK(status)) {
6139                 printf("writing print file data failed (%s)\n",
6140                         nt_errstr(status));
6141                 goto fail;
6142         }
6143
6144         status = cli_nt_delete_on_close(cli1, fnum1, true);
6145         if (!NT_STATUS_IS_OK(status)) {
6146                 printf("setting delete_on_close failed (%s)\n",
6147                         nt_errstr(status));
6148                 goto fail;
6149         }
6150
6151         status = cli_close(cli1, fnum1);
6152         if (!NT_STATUS_IS_OK(status)) {
6153                 printf("close failed (%s)\n", nt_errstr(status));
6154                 goto fail;
6155         }
6156
6157         printf("finished print delete test\n");
6158
6159         correct = true;
6160
6161   fail:
6162
6163         if (fnum1 != (uint16_t)-1) {
6164                 cli_close(cli1, fnum1);
6165         }
6166
6167         if (cli1 && !torture_close_connection(cli1)) {
6168                 correct = false;
6169         }
6170         return correct;
6171 }
6172
6173 static bool run_deletetest_ln(int dummy)
6174 {
6175         struct cli_state *cli;
6176         const char *fname = "\\delete1";
6177         const char *fname_ln = "\\delete1_ln";
6178         uint16_t fnum;
6179         uint16_t fnum1;
6180         NTSTATUS status;
6181         bool correct = true;
6182         time_t t;
6183
6184         printf("starting deletetest-ln\n");
6185
6186         if (!torture_open_connection(&cli, 0)) {
6187                 return false;
6188         }
6189
6190         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6191         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6192
6193         smbXcli_conn_set_sockopt(cli->conn, sockops);
6194
6195         /* Create the file. */
6196         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6197         if (!NT_STATUS_IS_OK(status)) {
6198                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6199                 return false;
6200         }
6201
6202         status = cli_close(cli, fnum);
6203         if (!NT_STATUS_IS_OK(status)) {
6204                 printf("close1 failed (%s)\n", nt_errstr(status));
6205                 return false;
6206         }
6207
6208         /* Now create a hardlink. */
6209         status = cli_hardlink(cli, fname, fname_ln);
6210         if (!NT_STATUS_IS_OK(status)) {
6211                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6212                 return false;
6213         }
6214
6215         /* Open the original file. */
6216         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6217                         FILE_ATTRIBUTE_NORMAL,
6218                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6219                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6220         if (!NT_STATUS_IS_OK(status)) {
6221                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6222                 return false;
6223         }
6224
6225         /* Unlink the hard link path. */
6226         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6227                         FILE_ATTRIBUTE_NORMAL,
6228                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6229                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6230         if (!NT_STATUS_IS_OK(status)) {
6231                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6232                 return false;
6233         }
6234         status = cli_nt_delete_on_close(cli, fnum1, true);
6235         if (!NT_STATUS_IS_OK(status)) {
6236                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6237                         __location__, fname_ln, nt_errstr(status));
6238                 return false;
6239         }
6240
6241         status = cli_close(cli, fnum1);
6242         if (!NT_STATUS_IS_OK(status)) {
6243                 printf("close %s failed (%s)\n",
6244                         fname_ln, nt_errstr(status));
6245                 return false;
6246         }
6247
6248         status = cli_close(cli, fnum);
6249         if (!NT_STATUS_IS_OK(status)) {
6250                 printf("close %s failed (%s)\n",
6251                         fname, nt_errstr(status));
6252                 return false;
6253         }
6254
6255         /* Ensure the original file is still there. */
6256         status = cli_getatr(cli, fname, NULL, NULL, &t);
6257         if (!NT_STATUS_IS_OK(status)) {
6258                 printf("%s getatr on file %s failed (%s)\n",
6259                         __location__,
6260                         fname,
6261                         nt_errstr(status));
6262                 correct = False;
6263         }
6264
6265         /* Ensure the link path is gone. */
6266         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6267         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6268                 printf("%s, getatr for file %s returned wrong error code %s "
6269                         "- should have been deleted\n",
6270                         __location__,
6271                         fname_ln, nt_errstr(status));
6272                 correct = False;
6273         }
6274
6275         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6276         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6277
6278         if (!torture_close_connection(cli)) {
6279                 correct = false;
6280         }
6281
6282         printf("finished deletetest-ln\n");
6283
6284         return correct;
6285 }
6286
6287 /*
6288   print out server properties
6289  */
6290 static bool run_properties(int dummy)
6291 {
6292         struct cli_state *cli;
6293         bool correct = True;
6294
6295         printf("starting properties test\n");
6296
6297         ZERO_STRUCT(cli);
6298
6299         if (!torture_open_connection(&cli, 0)) {
6300                 return False;
6301         }
6302
6303         smbXcli_conn_set_sockopt(cli->conn, sockops);
6304
6305         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6306
6307         if (!torture_close_connection(cli)) {
6308                 correct = False;
6309         }
6310
6311         return correct;
6312 }
6313
6314
6315
6316 /* FIRST_DESIRED_ACCESS   0xf019f */
6317 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6318                                FILE_READ_EA|                           /* 0xf */ \
6319                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6320                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6321                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6322                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6323 /* SECOND_DESIRED_ACCESS  0xe0080 */
6324 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6325                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6326                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6327
6328 #if 0
6329 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6330                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6331                                FILE_READ_DATA|\
6332                                WRITE_OWNER_ACCESS                      /* */
6333 #endif
6334
6335 /*
6336   Test ntcreate calls made by xcopy
6337  */
6338 static bool run_xcopy(int dummy)
6339 {
6340         static struct cli_state *cli1;
6341         const char *fname = "\\test.txt";
6342         bool correct = True;
6343         uint16_t fnum1, fnum2;
6344         NTSTATUS status;
6345
6346         printf("starting xcopy test\n");
6347
6348         if (!torture_open_connection(&cli1, 0)) {
6349                 return False;
6350         }
6351
6352         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6353                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6354                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6355         if (!NT_STATUS_IS_OK(status)) {
6356                 printf("First open failed - %s\n", nt_errstr(status));
6357                 return False;
6358         }
6359
6360         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6361                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6362                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6363         if (!NT_STATUS_IS_OK(status)) {
6364                 printf("second open failed - %s\n", nt_errstr(status));
6365                 return False;
6366         }
6367
6368         if (!torture_close_connection(cli1)) {
6369                 correct = False;
6370         }
6371
6372         return correct;
6373 }
6374
6375 /*
6376   Test rename on files open with share delete and no share delete.
6377  */
6378 static bool run_rename(int dummy)
6379 {
6380         static struct cli_state *cli1;
6381         const char *fname = "\\test.txt";
6382         const char *fname1 = "\\test1.txt";
6383         bool correct = True;
6384         uint16_t fnum1;
6385         uint32_t attr;
6386         NTSTATUS status;
6387
6388         printf("starting rename test\n");
6389
6390         if (!torture_open_connection(&cli1, 0)) {
6391                 return False;
6392         }
6393
6394         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6395         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6396
6397         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6398                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6399                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6400         if (!NT_STATUS_IS_OK(status)) {
6401                 printf("First open failed - %s\n", nt_errstr(status));
6402                 return False;
6403         }
6404
6405         status = cli_rename(cli1, fname, fname1, false);
6406         if (!NT_STATUS_IS_OK(status)) {
6407                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6408         } else {
6409                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6410                 correct = False;
6411         }
6412
6413         status = cli_close(cli1, fnum1);
6414         if (!NT_STATUS_IS_OK(status)) {
6415                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6416                 return False;
6417         }
6418
6419         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6420         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6421         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6422 #if 0
6423                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6424 #else
6425                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6426 #endif
6427                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6428         if (!NT_STATUS_IS_OK(status)) {
6429                 printf("Second open failed - %s\n", nt_errstr(status));
6430                 return False;
6431         }
6432
6433         status = cli_rename(cli1, fname, fname1, false);
6434         if (!NT_STATUS_IS_OK(status)) {
6435                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6436                 correct = False;
6437         } else {
6438                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6439         }
6440
6441         status = cli_close(cli1, fnum1);
6442         if (!NT_STATUS_IS_OK(status)) {
6443                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6444                 return False;
6445         }
6446
6447         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6448         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6449
6450         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6451                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6452                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6453         if (!NT_STATUS_IS_OK(status)) {
6454                 printf("Third open failed - %s\n", nt_errstr(status));
6455                 return False;
6456         }
6457
6458
6459         status = cli_rename(cli1, fname, fname1, false);
6460         if (!NT_STATUS_IS_OK(status)) {
6461                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6462                 correct = False;
6463         } else {
6464                 printf("Third rename succeeded (SHARE_NONE)\n");
6465         }
6466
6467         status = cli_close(cli1, fnum1);
6468         if (!NT_STATUS_IS_OK(status)) {
6469                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6470                 return False;
6471         }
6472
6473         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6474         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6475
6476         /*----*/
6477
6478         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6479                               FILE_ATTRIBUTE_NORMAL,
6480                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6481                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6482         if (!NT_STATUS_IS_OK(status)) {
6483                 printf("Fourth open failed - %s\n", nt_errstr(status));
6484                 return False;
6485         }
6486
6487         status = cli_rename(cli1, fname, fname1, false);
6488         if (!NT_STATUS_IS_OK(status)) {
6489                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6490         } else {
6491                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6492                 correct = False;
6493         }
6494
6495         status = cli_close(cli1, fnum1);
6496         if (!NT_STATUS_IS_OK(status)) {
6497                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6498                 return False;
6499         }
6500
6501         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6502         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6503
6504         /*--*/
6505
6506         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6507                          FILE_ATTRIBUTE_NORMAL,
6508                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6509                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6510         if (!NT_STATUS_IS_OK(status)) {
6511                 printf("Fifth open failed - %s\n", nt_errstr(status));
6512                 return False;
6513         }
6514
6515         status = cli_rename(cli1, fname, fname1, false);
6516         if (!NT_STATUS_IS_OK(status)) {
6517                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6518                 correct = False;
6519         } else {
6520                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6521         }
6522
6523         /*--*/
6524         status = cli_close(cli1, fnum1);
6525         if (!NT_STATUS_IS_OK(status)) {
6526                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6527                 return False;
6528         }
6529
6530         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6531         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6532         if (!NT_STATUS_IS_OK(status)) {
6533                 printf("getatr on file %s failed - %s ! \n",
6534                         fname1, nt_errstr(status));
6535                 correct = False;
6536         } else {
6537                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6538                         printf("Renamed file %s has wrong attr 0x%x "
6539                                 "(should be 0x%x)\n",
6540                                 fname1,
6541                                 attr,
6542                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6543                         correct = False;
6544                 } else {
6545                         printf("Renamed file %s has archive bit set\n", fname1);
6546                 }
6547         }
6548
6549         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6550         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6551
6552         if (!torture_close_connection(cli1)) {
6553                 correct = False;
6554         }
6555
6556         return correct;
6557 }
6558
6559 /*
6560   Test rename into a directory with an ACL denying it.
6561  */
6562 static bool run_rename_access(int dummy)
6563 {
6564         static struct cli_state *cli = NULL;
6565         static struct cli_state *posix_cli = NULL;
6566         const char *src = "test.txt";
6567         const char *dname = "dir";
6568         const char *dst = "dir\\test.txt";
6569         const char *dsrc = "test.dir";
6570         const char *ddst = "dir\\test.dir";
6571         uint16_t fnum = (uint16_t)-1;
6572         struct security_descriptor *sd = NULL;
6573         struct security_descriptor *newsd = NULL;
6574         NTSTATUS status;
6575         TALLOC_CTX *frame = NULL;
6576
6577         frame = talloc_stackframe();
6578         printf("starting rename access test\n");
6579
6580         /* Windows connection. */
6581         if (!torture_open_connection(&cli, 0)) {
6582                 goto fail;
6583         }
6584
6585         smbXcli_conn_set_sockopt(cli->conn, sockops);
6586
6587         /* Posix connection. */
6588         if (!torture_open_connection(&posix_cli, 0)) {
6589                 goto fail;
6590         }
6591
6592         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6593
6594         status = torture_setup_unix_extensions(posix_cli);
6595         if (!NT_STATUS_IS_OK(status)) {
6596                 goto fail;
6597         }
6598
6599         /* Start with a clean slate. */
6600         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6601         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6602         cli_rmdir(cli, dsrc);
6603         cli_rmdir(cli, ddst);
6604         cli_rmdir(cli, dname);
6605
6606         /*
6607          * Setup the destination directory with a DENY ACE to
6608          * prevent new files within it.
6609          */
6610         status = cli_ntcreate(cli,
6611                                 dname,
6612                                 0,
6613                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6614                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6615                                         WRITE_OWNER_ACCESS,
6616                                 FILE_ATTRIBUTE_DIRECTORY,
6617                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6618                                 FILE_CREATE,
6619                                 FILE_DIRECTORY_FILE,
6620                                 0,
6621                                 &fnum,
6622                                 NULL);
6623         if (!NT_STATUS_IS_OK(status)) {
6624                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6625                 goto fail;
6626         }
6627
6628         status = cli_query_secdesc(cli,
6629                                 fnum,
6630                                 frame,
6631                                 &sd);
6632         if (!NT_STATUS_IS_OK(status)) {
6633                 printf("cli_query_secdesc failed for %s (%s)\n",
6634                         dname, nt_errstr(status));
6635                 goto fail;
6636         }
6637
6638         newsd = security_descriptor_dacl_create(frame,
6639                                         0,
6640                                         NULL,
6641                                         NULL,
6642                                         SID_WORLD,
6643                                         SEC_ACE_TYPE_ACCESS_DENIED,
6644                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6645                                         0,
6646                                         NULL);
6647         if (newsd == NULL) {
6648                 goto fail;
6649         }
6650         sd->dacl = security_acl_concatenate(frame,
6651                                         newsd->dacl,
6652                                         sd->dacl);
6653         if (sd->dacl == NULL) {
6654                 goto fail;
6655         }
6656         status = cli_set_secdesc(cli, fnum, sd);
6657         if (!NT_STATUS_IS_OK(status)) {
6658                 printf("cli_set_secdesc failed for %s (%s)\n",
6659                         dname, nt_errstr(status));
6660                 goto fail;
6661         }
6662         status = cli_close(cli, fnum);
6663         if (!NT_STATUS_IS_OK(status)) {
6664                 printf("close failed for %s (%s)\n",
6665                         dname, nt_errstr(status));
6666                 goto fail;
6667         }
6668         /* Now go around the back and chmod to 777 via POSIX. */
6669         status = cli_posix_chmod(posix_cli, dname, 0777);
6670         if (!NT_STATUS_IS_OK(status)) {
6671                 printf("cli_posix_chmod failed for %s (%s)\n",
6672                         dname, nt_errstr(status));
6673                 goto fail;
6674         }
6675
6676         /* Check we can't create a file within dname via Windows. */
6677         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6678         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6679                 cli_close(posix_cli, fnum);
6680                 printf("Create of %s should be ACCESS denied, was %s\n",
6681                         dst, nt_errstr(status));
6682                 goto fail;
6683         }
6684
6685         /* Make the sample file/directory. */
6686         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6687         if (!NT_STATUS_IS_OK(status)) {
6688                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6689                 goto fail;
6690         }
6691         status = cli_close(cli, fnum);
6692         if (!NT_STATUS_IS_OK(status)) {
6693                 printf("cli_close failed (%s)\n", nt_errstr(status));
6694                 goto fail;
6695         }
6696
6697         status = cli_mkdir(cli, dsrc);
6698         if (!NT_STATUS_IS_OK(status)) {
6699                 printf("cli_mkdir of %s failed (%s)\n",
6700                         dsrc, nt_errstr(status));
6701                 goto fail;
6702         }
6703
6704         /*
6705          * OK - renames of the new file and directory into the
6706          * dst directory should fail.
6707          */
6708
6709         status = cli_rename(cli, src, dst, false);
6710         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6711                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6712                         src, dst, nt_errstr(status));
6713                 goto fail;
6714         }
6715         status = cli_rename(cli, dsrc, ddst, false);
6716         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6717                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6718                         src, dst, nt_errstr(status));
6719                 goto fail;
6720         }
6721
6722         TALLOC_FREE(frame);
6723         return true;
6724
6725   fail:
6726
6727         if (posix_cli) {
6728                 torture_close_connection(posix_cli);
6729         }
6730
6731         if (cli) {
6732                 if (fnum != (uint16_t)-1) {
6733                         cli_close(cli, fnum);
6734                 }
6735                 cli_unlink(cli, src,
6736                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6737                 cli_unlink(cli, dst,
6738                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6739                 cli_rmdir(cli, dsrc);
6740                 cli_rmdir(cli, ddst);
6741                 cli_rmdir(cli, dname);
6742
6743                 torture_close_connection(cli);
6744         }
6745
6746         TALLOC_FREE(frame);
6747         return false;
6748 }
6749
6750 /*
6751   Test owner rights ACE.
6752  */
6753 static bool run_owner_rights(int dummy)
6754 {
6755         static struct cli_state *cli = NULL;
6756         const char *fname = "owner_rights.txt";
6757         uint16_t fnum = (uint16_t)-1;
6758         struct security_descriptor *sd = NULL;
6759         struct security_descriptor *newsd = NULL;
6760         NTSTATUS status;
6761         TALLOC_CTX *frame = NULL;
6762
6763         frame = talloc_stackframe();
6764         printf("starting owner rights test\n");
6765
6766         /* Windows connection. */
6767         if (!torture_open_connection(&cli, 0)) {
6768                 goto fail;
6769         }
6770
6771         smbXcli_conn_set_sockopt(cli->conn, sockops);
6772
6773         /* Start with a clean slate. */
6774         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6775
6776         /* Create the test file. */
6777         /* Now try and open for read and write-dac. */
6778         status = cli_ntcreate(cli,
6779                                 fname,
6780                                 0,
6781                                 GENERIC_ALL_ACCESS,
6782                                 FILE_ATTRIBUTE_NORMAL,
6783                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6784                                         FILE_SHARE_DELETE,
6785                                 FILE_CREATE,
6786                                 0,
6787                                 0,
6788                                 &fnum,
6789                                 NULL);
6790         if (!NT_STATUS_IS_OK(status)) {
6791                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6792                 goto fail;
6793         }
6794
6795         /* Get the original SD. */
6796         status = cli_query_secdesc(cli,
6797                                 fnum,
6798                                 frame,
6799                                 &sd);
6800         if (!NT_STATUS_IS_OK(status)) {
6801                 printf("cli_query_secdesc failed for %s (%s)\n",
6802                         fname, nt_errstr(status));
6803                 goto fail;
6804         }
6805
6806         /*
6807          * Add an "owner-rights" ACE denying WRITE_DATA,
6808          * and an "owner-rights" ACE allowing READ_DATA.
6809          */
6810
6811         newsd = security_descriptor_dacl_create(frame,
6812                                         0,
6813                                         NULL,
6814                                         NULL,
6815                                         SID_OWNER_RIGHTS,
6816                                         SEC_ACE_TYPE_ACCESS_DENIED,
6817                                         FILE_WRITE_DATA,
6818                                         0,
6819                                         SID_OWNER_RIGHTS,
6820                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6821                                         FILE_READ_DATA,
6822                                         0,
6823                                         NULL);
6824         if (newsd == NULL) {
6825                 goto fail;
6826         }
6827         sd->dacl = security_acl_concatenate(frame,
6828                                         newsd->dacl,
6829                                         sd->dacl);
6830         if (sd->dacl == NULL) {
6831                 goto fail;
6832         }
6833         status = cli_set_secdesc(cli, fnum, sd);
6834         if (!NT_STATUS_IS_OK(status)) {
6835                 printf("cli_set_secdesc failed for %s (%s)\n",
6836                         fname, nt_errstr(status));
6837                 goto fail;
6838         }
6839         status = cli_close(cli, fnum);
6840         if (!NT_STATUS_IS_OK(status)) {
6841                 printf("close failed for %s (%s)\n",
6842                         fname, nt_errstr(status));
6843                 goto fail;
6844         }
6845         fnum = (uint16_t)-1;
6846
6847         /* Try and open for FILE_WRITE_DATA */
6848         status = cli_ntcreate(cli,
6849                                 fname,
6850                                 0,
6851                                 FILE_WRITE_DATA,
6852                                 FILE_ATTRIBUTE_NORMAL,
6853                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6854                                         FILE_SHARE_DELETE,
6855                                 FILE_OPEN,
6856                                 0,
6857                                 0,
6858                                 &fnum,
6859                                 NULL);
6860         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6861                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6862                 goto fail;
6863         }
6864
6865         /* Now try and open for FILE_READ_DATA */
6866         status = cli_ntcreate(cli,
6867                                 fname,
6868                                 0,
6869                                 FILE_READ_DATA,
6870                                 FILE_ATTRIBUTE_NORMAL,
6871                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6872                                         FILE_SHARE_DELETE,
6873                                 FILE_OPEN,
6874                                 0,
6875                                 0,
6876                                 &fnum,
6877                                 NULL);
6878         if (!NT_STATUS_IS_OK(status)) {
6879                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6880                 goto fail;
6881         }
6882
6883         status = cli_close(cli, fnum);
6884         if (!NT_STATUS_IS_OK(status)) {
6885                 printf("close failed for %s (%s)\n",
6886                         fname, nt_errstr(status));
6887                 goto fail;
6888         }
6889
6890         /* Restore clean slate. */
6891         TALLOC_FREE(sd);
6892         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6893
6894         /* Create the test file. */
6895         status = cli_ntcreate(cli,
6896                                 fname,
6897                                 0,
6898                                 GENERIC_ALL_ACCESS,
6899                                 FILE_ATTRIBUTE_NORMAL,
6900                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6901                                         FILE_SHARE_DELETE,
6902                                 FILE_CREATE,
6903                                 0,
6904                                 0,
6905                                 &fnum,
6906                                 NULL);
6907         if (!NT_STATUS_IS_OK(status)) {
6908                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6909                 goto fail;
6910         }
6911
6912         /* Get the original SD. */
6913         status = cli_query_secdesc(cli,
6914                                 fnum,
6915                                 frame,
6916                                 &sd);
6917         if (!NT_STATUS_IS_OK(status)) {
6918                 printf("cli_query_secdesc failed for %s (%s)\n",
6919                         fname, nt_errstr(status));
6920                 goto fail;
6921         }
6922
6923         /*
6924          * Add an "owner-rights ACE denying WRITE_DATA,
6925          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6926          */
6927
6928         newsd = security_descriptor_dacl_create(frame,
6929                                         0,
6930                                         NULL,
6931                                         NULL,
6932                                         SID_OWNER_RIGHTS,
6933                                         SEC_ACE_TYPE_ACCESS_DENIED,
6934                                         FILE_WRITE_DATA,
6935                                         0,
6936                                         SID_OWNER_RIGHTS,
6937                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6938                                         FILE_READ_DATA|FILE_WRITE_DATA,
6939                                         0,
6940                                         NULL);
6941         if (newsd == NULL) {
6942                 goto fail;
6943         }
6944         sd->dacl = security_acl_concatenate(frame,
6945                                         newsd->dacl,
6946                                         sd->dacl);
6947         if (sd->dacl == NULL) {
6948                 goto fail;
6949         }
6950         status = cli_set_secdesc(cli, fnum, sd);
6951         if (!NT_STATUS_IS_OK(status)) {
6952                 printf("cli_set_secdesc failed for %s (%s)\n",
6953                         fname, nt_errstr(status));
6954                 goto fail;
6955         }
6956         status = cli_close(cli, fnum);
6957         if (!NT_STATUS_IS_OK(status)) {
6958                 printf("close failed for %s (%s)\n",
6959                         fname, nt_errstr(status));
6960                 goto fail;
6961         }
6962         fnum = (uint16_t)-1;
6963
6964         /* Try and open for FILE_WRITE_DATA */
6965         status = cli_ntcreate(cli,
6966                                 fname,
6967                                 0,
6968                                 FILE_WRITE_DATA,
6969                                 FILE_ATTRIBUTE_NORMAL,
6970                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6971                                         FILE_SHARE_DELETE,
6972                                 FILE_OPEN,
6973                                 0,
6974                                 0,
6975                                 &fnum,
6976                                 NULL);
6977         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6978                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6979                 goto fail;
6980         }
6981
6982         /* Now try and open for FILE_READ_DATA */
6983         status = cli_ntcreate(cli,
6984                                 fname,
6985                                 0,
6986                                 FILE_READ_DATA,
6987                                 FILE_ATTRIBUTE_NORMAL,
6988                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6989                                         FILE_SHARE_DELETE,
6990                                 FILE_OPEN,
6991                                 0,
6992                                 0,
6993                                 &fnum,
6994                                 NULL);
6995         if (!NT_STATUS_IS_OK(status)) {
6996                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6997                 goto fail;
6998         }
6999
7000         status = cli_close(cli, fnum);
7001         if (!NT_STATUS_IS_OK(status)) {
7002                 printf("close failed for %s (%s)\n",
7003                         fname, nt_errstr(status));
7004                 goto fail;
7005         }
7006
7007         /* Restore clean slate. */
7008         TALLOC_FREE(sd);
7009         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7010
7011
7012         /* Create the test file. */
7013         status = cli_ntcreate(cli,
7014                                 fname,
7015                                 0,
7016                                 GENERIC_ALL_ACCESS,
7017                                 FILE_ATTRIBUTE_NORMAL,
7018                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7019                                         FILE_SHARE_DELETE,
7020                                 FILE_CREATE,
7021                                 0,
7022                                 0,
7023                                 &fnum,
7024                                 NULL);
7025         if (!NT_STATUS_IS_OK(status)) {
7026                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7027                 goto fail;
7028         }
7029
7030         /* Get the original SD. */
7031         status = cli_query_secdesc(cli,
7032                                 fnum,
7033                                 frame,
7034                                 &sd);
7035         if (!NT_STATUS_IS_OK(status)) {
7036                 printf("cli_query_secdesc failed for %s (%s)\n",
7037                         fname, nt_errstr(status));
7038                 goto fail;
7039         }
7040
7041         /*
7042          * Add an "authenticated users" ACE allowing READ_DATA,
7043          * add an "owner-rights" denying READ_DATA,
7044          * and an "authenticated users" ACE allowing WRITE_DATA.
7045          */
7046
7047         newsd = security_descriptor_dacl_create(frame,
7048                                         0,
7049                                         NULL,
7050                                         NULL,
7051                                         SID_NT_AUTHENTICATED_USERS,
7052                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7053                                         FILE_READ_DATA,
7054                                         0,
7055                                         SID_OWNER_RIGHTS,
7056                                         SEC_ACE_TYPE_ACCESS_DENIED,
7057                                         FILE_READ_DATA,
7058                                         0,
7059                                         SID_NT_AUTHENTICATED_USERS,
7060                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7061                                         FILE_WRITE_DATA,
7062                                         0,
7063                                         NULL);
7064         if (newsd == NULL) {
7065                 printf("newsd == NULL\n");
7066                 goto fail;
7067         }
7068         sd->dacl = security_acl_concatenate(frame,
7069                                         newsd->dacl,
7070                                         sd->dacl);
7071         if (sd->dacl == NULL) {
7072                 printf("sd->dacl == NULL\n");
7073                 goto fail;
7074         }
7075         status = cli_set_secdesc(cli, fnum, sd);
7076         if (!NT_STATUS_IS_OK(status)) {
7077                 printf("cli_set_secdesc failed for %s (%s)\n",
7078                         fname, nt_errstr(status));
7079                 goto fail;
7080         }
7081         status = cli_close(cli, fnum);
7082         if (!NT_STATUS_IS_OK(status)) {
7083                 printf("close failed for %s (%s)\n",
7084                         fname, nt_errstr(status));
7085                 goto fail;
7086         }
7087         fnum = (uint16_t)-1;
7088
7089         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7090         status = cli_ntcreate(cli,
7091                                 fname,
7092                                 0,
7093                                 FILE_READ_DATA|FILE_WRITE_DATA,
7094                                 FILE_ATTRIBUTE_NORMAL,
7095                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7096                                         FILE_SHARE_DELETE,
7097                                 FILE_OPEN,
7098                                 0,
7099                                 0,
7100                                 &fnum,
7101                                 NULL);
7102         if (!NT_STATUS_IS_OK(status)) {
7103                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7104                 goto fail;
7105         }
7106
7107         status = cli_close(cli, fnum);
7108         if (!NT_STATUS_IS_OK(status)) {
7109                 printf("close failed for %s (%s)\n",
7110                         fname, nt_errstr(status));
7111                 goto fail;
7112         }
7113
7114         cli_unlink(cli, fname,
7115                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7116
7117         TALLOC_FREE(frame);
7118         return true;
7119
7120   fail:
7121
7122         if (cli) {
7123                 if (fnum != (uint16_t)-1) {
7124                         cli_close(cli, fnum);
7125                 }
7126                 cli_unlink(cli, fname,
7127                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7128                 torture_close_connection(cli);
7129         }
7130
7131         TALLOC_FREE(frame);
7132         return false;
7133 }
7134
7135 /*
7136  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7137  * Note this test only works with a user with SeSecurityPrivilege set.
7138  *
7139  * NB. This is also tested in samba3.base.createx_access
7140  * but this makes it very explicit what we're looking for.
7141  */
7142 static bool run_smb1_system_security(int dummy)
7143 {
7144         static struct cli_state *cli = NULL;
7145         const char *fname = "system_security.txt";
7146         uint16_t fnum = (uint16_t)-1;
7147         NTSTATUS status;
7148         TALLOC_CTX *frame = NULL;
7149
7150         frame = talloc_stackframe();
7151         printf("starting smb1 system security test\n");
7152
7153         /* SMB1 connection - torture_open_connection() forces this. */
7154         if (!torture_open_connection(&cli, 0)) {
7155                 goto fail;
7156         }
7157
7158         smbXcli_conn_set_sockopt(cli->conn, sockops);
7159
7160         /* Start with a clean slate. */
7161         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7162
7163         /* Create the test file. */
7164         status = cli_ntcreate(cli,
7165                                 fname,
7166                                 0,
7167                                 GENERIC_ALL_ACCESS,
7168                                 FILE_ATTRIBUTE_NORMAL,
7169                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7170                                         FILE_SHARE_DELETE,
7171                                 FILE_CREATE,
7172                                 0,
7173                                 0,
7174                                 &fnum,
7175                                 NULL);
7176         if (!NT_STATUS_IS_OK(status)) {
7177                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7178                 goto fail;
7179         }
7180
7181         status = cli_close(cli, fnum);
7182
7183         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7184         /*
7185          * On SMB1 this succeeds - SMB2 it fails,
7186          * see the SMB2-SACL test.
7187          */
7188         status = cli_ntcreate(cli,
7189                                 fname,
7190                                 0,
7191                                 SEC_FLAG_SYSTEM_SECURITY,
7192                                 FILE_ATTRIBUTE_NORMAL,
7193                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7194                                         FILE_SHARE_DELETE,
7195                                 FILE_OPEN,
7196                                 0,
7197                                 0,
7198                                 &fnum,
7199                                 NULL);
7200         if (!NT_STATUS_IS_OK(status)) {
7201                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7202                 goto fail;
7203         }
7204
7205         status = cli_close(cli, fnum);
7206
7207         cli_unlink(cli, fname,
7208                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7209
7210         torture_close_connection(cli);
7211         TALLOC_FREE(frame);
7212         return true;
7213
7214   fail:
7215
7216         if (cli) {
7217                 if (fnum != (uint16_t)-1) {
7218                         cli_close(cli, fnum);
7219                 }
7220                 cli_unlink(cli, fname,
7221                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7222                 torture_close_connection(cli);
7223         }
7224
7225         TALLOC_FREE(frame);
7226         return false;
7227 }
7228
7229 static bool run_pipe_number(int dummy)
7230 {
7231         struct cli_state *cli1;
7232         const char *pipe_name = "\\SPOOLSS";
7233         uint16_t fnum;
7234         int num_pipes = 0;
7235         NTSTATUS status;
7236
7237         printf("starting pipenumber test\n");
7238         if (!torture_open_connection(&cli1, 0)) {
7239                 return False;
7240         }
7241
7242         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7243         while(1) {
7244                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7245                                       FILE_ATTRIBUTE_NORMAL,
7246                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7247                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7248                 if (!NT_STATUS_IS_OK(status)) {
7249                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7250                         break;
7251                 }
7252                 num_pipes++;
7253                 printf("\r%6d", num_pipes);
7254         }
7255
7256         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7257         torture_close_connection(cli1);
7258         return True;
7259 }
7260
7261 /*
7262   Test open mode returns on read-only files.
7263  */
7264 static bool run_opentest(int dummy)
7265 {
7266         static struct cli_state *cli1;
7267         static struct cli_state *cli2;
7268         const char *fname = "\\readonly.file";
7269         uint16_t fnum1, fnum2;
7270         char buf[20];
7271         off_t fsize;
7272         bool correct = True;
7273         char *tmp_path;
7274         NTSTATUS status;
7275
7276         printf("starting open test\n");
7277
7278         if (!torture_open_connection(&cli1, 0)) {
7279                 return False;
7280         }
7281
7282         cli_setatr(cli1, fname, 0, 0);
7283         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7284
7285         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7286
7287         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7288         if (!NT_STATUS_IS_OK(status)) {
7289                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7290                 return False;
7291         }
7292
7293         status = cli_close(cli1, fnum1);
7294         if (!NT_STATUS_IS_OK(status)) {
7295                 printf("close2 failed (%s)\n", nt_errstr(status));
7296                 return False;
7297         }
7298
7299         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7300         if (!NT_STATUS_IS_OK(status)) {
7301                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7302                 return False;
7303         }
7304
7305         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7306         if (!NT_STATUS_IS_OK(status)) {
7307                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7308                 return False;
7309         }
7310
7311         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7312         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7313
7314         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7315                         NT_STATUS_ACCESS_DENIED)) {
7316                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7317         }
7318
7319         printf("finished open test 1\n");
7320
7321         cli_close(cli1, fnum1);
7322
7323         /* Now try not readonly and ensure ERRbadshare is returned. */
7324
7325         cli_setatr(cli1, fname, 0, 0);
7326
7327         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7328         if (!NT_STATUS_IS_OK(status)) {
7329                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7330                 return False;
7331         }
7332
7333         /* This will fail - but the error should be ERRshare. */
7334         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7335
7336         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7337                         NT_STATUS_SHARING_VIOLATION)) {
7338                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7339         }
7340
7341         status = cli_close(cli1, fnum1);
7342         if (!NT_STATUS_IS_OK(status)) {
7343                 printf("close2 failed (%s)\n", nt_errstr(status));
7344                 return False;
7345         }
7346
7347         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7348
7349         printf("finished open test 2\n");
7350
7351         /* Test truncate open disposition on file opened for read. */
7352         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7353         if (!NT_STATUS_IS_OK(status)) {
7354                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7355                 return False;
7356         }
7357
7358         /* write 20 bytes. */
7359
7360         memset(buf, '\0', 20);
7361
7362         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7363         if (!NT_STATUS_IS_OK(status)) {
7364                 printf("write failed (%s)\n", nt_errstr(status));
7365                 correct = False;
7366         }
7367
7368         status = cli_close(cli1, fnum1);
7369         if (!NT_STATUS_IS_OK(status)) {
7370                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7371                 return False;
7372         }
7373
7374         /* Ensure size == 20. */
7375         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7376         if (!NT_STATUS_IS_OK(status)) {
7377                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7378                 return False;
7379         }
7380
7381         if (fsize != 20) {
7382                 printf("(3) file size != 20\n");
7383                 return False;
7384         }
7385
7386         /* Now test if we can truncate a file opened for readonly. */
7387         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7388         if (!NT_STATUS_IS_OK(status)) {
7389                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7390                 return False;
7391         }
7392
7393         status = cli_close(cli1, fnum1);
7394         if (!NT_STATUS_IS_OK(status)) {
7395                 printf("close2 failed (%s)\n", nt_errstr(status));
7396                 return False;
7397         }
7398
7399         /* Ensure size == 0. */
7400         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7401         if (!NT_STATUS_IS_OK(status)) {
7402                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7403                 return False;
7404         }
7405
7406         if (fsize != 0) {
7407                 printf("(3) file size != 0\n");
7408                 return False;
7409         }
7410         printf("finished open test 3\n");
7411
7412         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7413
7414         printf("Do ctemp tests\n");
7415         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7416         if (!NT_STATUS_IS_OK(status)) {
7417                 printf("ctemp failed (%s)\n", nt_errstr(status));
7418                 return False;
7419         }
7420
7421         printf("ctemp gave path %s\n", tmp_path);
7422         status = cli_close(cli1, fnum1);
7423         if (!NT_STATUS_IS_OK(status)) {
7424                 printf("close of temp failed (%s)\n", nt_errstr(status));
7425         }
7426
7427         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7428         if (!NT_STATUS_IS_OK(status)) {
7429                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7430         }
7431
7432         /* Test the non-io opens... */
7433
7434         if (!torture_open_connection(&cli2, 1)) {
7435                 return False;
7436         }
7437
7438         cli_setatr(cli2, fname, 0, 0);
7439         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7440
7441         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7442
7443         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7444         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7445                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7446                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7447         if (!NT_STATUS_IS_OK(status)) {
7448                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7449                 return False;
7450         }
7451
7452         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7453                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7454                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7455         if (!NT_STATUS_IS_OK(status)) {
7456                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7457                 return False;
7458         }
7459
7460         status = cli_close(cli1, fnum1);
7461         if (!NT_STATUS_IS_OK(status)) {
7462                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7463                 return False;
7464         }
7465
7466         status = cli_close(cli2, fnum2);
7467         if (!NT_STATUS_IS_OK(status)) {
7468                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7469                 return False;
7470         }
7471
7472         printf("non-io open test #1 passed.\n");
7473
7474         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7475
7476         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7477
7478         status = cli_ntcreate(cli1, fname, 0,
7479                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7480                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7481                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7482         if (!NT_STATUS_IS_OK(status)) {
7483                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7484                 return False;
7485         }
7486
7487         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7488                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7489                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7490         if (!NT_STATUS_IS_OK(status)) {
7491                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7492                 return False;
7493         }
7494
7495         status = cli_close(cli1, fnum1);
7496         if (!NT_STATUS_IS_OK(status)) {
7497                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7498                 return False;
7499         }
7500
7501         status = cli_close(cli2, fnum2);
7502         if (!NT_STATUS_IS_OK(status)) {
7503                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7504                 return False;
7505         }
7506
7507         printf("non-io open test #2 passed.\n");
7508
7509         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7510
7511         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7512
7513         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7514                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7515                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7516         if (!NT_STATUS_IS_OK(status)) {
7517                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7518                 return False;
7519         }
7520
7521         status = cli_ntcreate(cli2, fname, 0,
7522                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7523                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7524                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7525         if (!NT_STATUS_IS_OK(status)) {
7526                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7527                 return False;
7528         }
7529
7530         status = cli_close(cli1, fnum1);
7531         if (!NT_STATUS_IS_OK(status)) {
7532                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7533                 return False;
7534         }
7535
7536         status = cli_close(cli2, fnum2);
7537         if (!NT_STATUS_IS_OK(status)) {
7538                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7539                 return False;
7540         }
7541
7542         printf("non-io open test #3 passed.\n");
7543
7544         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7545
7546         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7547
7548         status = cli_ntcreate(cli1, fname, 0,
7549                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7550                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7551                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7552         if (!NT_STATUS_IS_OK(status)) {
7553                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7554                 return False;
7555         }
7556
7557         status = cli_ntcreate(cli2, fname, 0,
7558                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7559                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7560                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7561         if (NT_STATUS_IS_OK(status)) {
7562                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7563                 return False;
7564         }
7565
7566         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7567
7568         status = cli_close(cli1, fnum1);
7569         if (!NT_STATUS_IS_OK(status)) {
7570                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7571                 return False;
7572         }
7573
7574         printf("non-io open test #4 passed.\n");
7575
7576         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7577
7578         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7579
7580         status = cli_ntcreate(cli1, fname, 0,
7581                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7582                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7583                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7584         if (!NT_STATUS_IS_OK(status)) {
7585                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7586                 return False;
7587         }
7588
7589         status = cli_ntcreate(cli2, fname, 0,
7590                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7591                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7592                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7593         if (!NT_STATUS_IS_OK(status)) {
7594                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7595                 return False;
7596         }
7597
7598         status = cli_close(cli1, fnum1);
7599         if (!NT_STATUS_IS_OK(status)) {
7600                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7601                 return False;
7602         }
7603
7604         status = cli_close(cli2, fnum2);
7605         if (!NT_STATUS_IS_OK(status)) {
7606                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7607                 return False;
7608         }
7609
7610         printf("non-io open test #5 passed.\n");
7611
7612         printf("TEST #6 testing 1 non-io open, one io open\n");
7613
7614         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7615
7616         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7617                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7618                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7619         if (!NT_STATUS_IS_OK(status)) {
7620                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7621                 return False;
7622         }
7623
7624         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7625                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7626                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7627         if (!NT_STATUS_IS_OK(status)) {
7628                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7629                 return False;
7630         }
7631
7632         status = cli_close(cli1, fnum1);
7633         if (!NT_STATUS_IS_OK(status)) {
7634                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7635                 return False;
7636         }
7637
7638         status = cli_close(cli2, fnum2);
7639         if (!NT_STATUS_IS_OK(status)) {
7640                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7641                 return False;
7642         }
7643
7644         printf("non-io open test #6 passed.\n");
7645
7646         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7647
7648         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7649
7650         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7651                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7652                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7653         if (!NT_STATUS_IS_OK(status)) {
7654                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7655                 return False;
7656         }
7657
7658         status = cli_ntcreate(cli2, fname, 0,
7659                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7660                               FILE_ATTRIBUTE_NORMAL,
7661                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7662                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7663         if (NT_STATUS_IS_OK(status)) {
7664                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7665                 return False;
7666         }
7667
7668         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7669
7670         status = cli_close(cli1, fnum1);
7671         if (!NT_STATUS_IS_OK(status)) {
7672                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7673                 return False;
7674         }
7675
7676         printf("non-io open test #7 passed.\n");
7677
7678         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7679
7680         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7681         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7682                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7683                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7684         if (!NT_STATUS_IS_OK(status)) {
7685                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7686                 correct = false;
7687                 goto out;
7688         }
7689
7690         /* Write to ensure we have to update the file time. */
7691         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7692                               NULL);
7693         if (!NT_STATUS_IS_OK(status)) {
7694                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7695                 correct = false;
7696                 goto out;
7697         }
7698
7699         status = cli_close(cli1, fnum1);
7700         if (!NT_STATUS_IS_OK(status)) {
7701                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7702                 correct = false;
7703         }
7704
7705   out:
7706
7707         if (!torture_close_connection(cli1)) {
7708                 correct = False;
7709         }
7710         if (!torture_close_connection(cli2)) {
7711                 correct = False;
7712         }
7713
7714         return correct;
7715 }
7716
7717 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7718 {
7719         uint16_t major, minor;
7720         uint32_t caplow, caphigh;
7721         NTSTATUS status;
7722
7723         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7724                 printf("Server doesn't support UNIX CIFS extensions.\n");
7725                 return NT_STATUS_NOT_SUPPORTED;
7726         }
7727
7728         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7729                                              &caphigh);
7730         if (!NT_STATUS_IS_OK(status)) {
7731                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7732                        nt_errstr(status));
7733                 return status;
7734         }
7735
7736         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7737                                                       caplow, caphigh);
7738         if (!NT_STATUS_IS_OK(status)) {
7739                 printf("Server doesn't support setting UNIX CIFS extensions: "
7740                        "%s.\n", nt_errstr(status));
7741                 return status;
7742         }
7743
7744         return NT_STATUS_OK;
7745 }
7746
7747 /*
7748   Test POSIX open /mkdir calls.
7749  */
7750 static bool run_simple_posix_open_test(int dummy)
7751 {
7752         static struct cli_state *cli1;
7753         const char *fname = "posix:file";
7754         const char *hname = "posix:hlink";
7755         const char *sname = "posix:symlink";
7756         const char *dname = "posix:dir";
7757         char buf[10];
7758         char *target = NULL;
7759         uint16_t fnum1 = (uint16_t)-1;
7760         SMB_STRUCT_STAT sbuf;
7761         bool correct = false;
7762         NTSTATUS status;
7763         size_t nread;
7764         const char *fname_windows = "windows_file";
7765         uint16_t fnum2 = (uint16_t)-1;
7766         bool ok;
7767
7768         printf("Starting simple POSIX open test\n");
7769
7770         if (!torture_open_connection(&cli1, 0)) {
7771                 return false;
7772         }
7773
7774         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7775
7776         status = torture_setup_unix_extensions(cli1);
7777         if (!NT_STATUS_IS_OK(status)) {
7778                 return false;
7779         }
7780
7781         cli_setatr(cli1, fname, 0, 0);
7782         cli_posix_unlink(cli1, fname);
7783         cli_setatr(cli1, dname, 0, 0);
7784         cli_posix_rmdir(cli1, dname);
7785         cli_setatr(cli1, hname, 0, 0);
7786         cli_posix_unlink(cli1, hname);
7787         cli_setatr(cli1, sname, 0, 0);
7788         cli_posix_unlink(cli1, sname);
7789         cli_setatr(cli1, fname_windows, 0, 0);
7790         cli_posix_unlink(cli1, fname_windows);
7791
7792         /* Create a directory. */
7793         status = cli_posix_mkdir(cli1, dname, 0777);
7794         if (!NT_STATUS_IS_OK(status)) {
7795                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7796                 goto out;
7797         }
7798
7799         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7800                                 0600, &fnum1);
7801         if (!NT_STATUS_IS_OK(status)) {
7802                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7803                 goto out;
7804         }
7805
7806         /* Test ftruncate - set file size. */
7807         status = cli_ftruncate(cli1, fnum1, 1000);
7808         if (!NT_STATUS_IS_OK(status)) {
7809                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7810                 goto out;
7811         }
7812
7813         /* Ensure st_size == 1000 */
7814         status = cli_posix_stat(cli1, fname, &sbuf);
7815         if (!NT_STATUS_IS_OK(status)) {
7816                 printf("stat failed (%s)\n", nt_errstr(status));
7817                 goto out;
7818         }
7819
7820         if (sbuf.st_ex_size != 1000) {
7821                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7822                 goto out;
7823         }
7824
7825         /* Ensure st_mode == 0600 */
7826         if ((sbuf.st_ex_mode & 07777) != 0600) {
7827                 printf("posix_open - bad permissions 0%o != 0600\n",
7828                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7829                 goto out;
7830         }
7831
7832         /* Test ftruncate - set file size back to zero. */
7833         status = cli_ftruncate(cli1, fnum1, 0);
7834         if (!NT_STATUS_IS_OK(status)) {
7835                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7836                 goto out;
7837         }
7838
7839         status = cli_close(cli1, fnum1);
7840         if (!NT_STATUS_IS_OK(status)) {
7841                 printf("close failed (%s)\n", nt_errstr(status));
7842                 goto out;
7843         }
7844
7845         /* Now open the file again for read only. */
7846         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7847         if (!NT_STATUS_IS_OK(status)) {
7848                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7849                 goto out;
7850         }
7851
7852         /* Now unlink while open. */
7853         status = cli_posix_unlink(cli1, fname);
7854         if (!NT_STATUS_IS_OK(status)) {
7855                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7856                 goto out;
7857         }
7858
7859         status = cli_close(cli1, fnum1);
7860         if (!NT_STATUS_IS_OK(status)) {
7861                 printf("close(2) failed (%s)\n", nt_errstr(status));
7862                 goto out;
7863         }
7864
7865         /* Ensure the file has gone. */
7866         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7867         if (NT_STATUS_IS_OK(status)) {
7868                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7869                 goto out;
7870         }
7871
7872         /* Create again to test open with O_TRUNC. */
7873         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7874         if (!NT_STATUS_IS_OK(status)) {
7875                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7876                 goto out;
7877         }
7878
7879         /* Test ftruncate - set file size. */
7880         status = cli_ftruncate(cli1, fnum1, 1000);
7881         if (!NT_STATUS_IS_OK(status)) {
7882                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7883                 goto out;
7884         }
7885
7886         /* Ensure st_size == 1000 */
7887         status = cli_posix_stat(cli1, fname, &sbuf);
7888         if (!NT_STATUS_IS_OK(status)) {
7889                 printf("stat failed (%s)\n", nt_errstr(status));
7890                 goto out;
7891         }
7892
7893         if (sbuf.st_ex_size != 1000) {
7894                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7895                 goto out;
7896         }
7897
7898         status = cli_close(cli1, fnum1);
7899         if (!NT_STATUS_IS_OK(status)) {
7900                 printf("close(2) failed (%s)\n", nt_errstr(status));
7901                 goto out;
7902         }
7903
7904         /* Re-open with O_TRUNC. */
7905         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7906         if (!NT_STATUS_IS_OK(status)) {
7907                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7908                 goto out;
7909         }
7910
7911         /* Ensure st_size == 0 */
7912         status = cli_posix_stat(cli1, fname, &sbuf);
7913         if (!NT_STATUS_IS_OK(status)) {
7914                 printf("stat failed (%s)\n", nt_errstr(status));
7915                 goto out;
7916         }
7917
7918         if (sbuf.st_ex_size != 0) {
7919                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7920                 goto out;
7921         }
7922
7923         status = cli_close(cli1, fnum1);
7924         if (!NT_STATUS_IS_OK(status)) {
7925                 printf("close failed (%s)\n", nt_errstr(status));
7926                 goto out;
7927         }
7928
7929         status = cli_posix_unlink(cli1, fname);
7930         if (!NT_STATUS_IS_OK(status)) {
7931                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7932                 goto out;
7933         }
7934
7935         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7936         if (!NT_STATUS_IS_OK(status)) {
7937                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7938                         dname, nt_errstr(status));
7939                 goto out;
7940         }
7941
7942         cli_close(cli1, fnum1);
7943
7944         /* What happens when we try and POSIX open a directory for write ? */
7945         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7946         if (NT_STATUS_IS_OK(status)) {
7947                 printf("POSIX open of directory %s succeeded, "
7948                        "should have failed.\n",
7949                        dname);
7950                 goto out;
7951         } else {
7952                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7953                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7954                         goto out;
7955                 }
7956         }
7957
7958         /* Create the file. */
7959         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7960                                 0600, &fnum1);
7961         if (!NT_STATUS_IS_OK(status)) {
7962                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7963                 goto out;
7964         }
7965
7966         /* Write some data into it. */
7967         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7968                               NULL);
7969         if (!NT_STATUS_IS_OK(status)) {
7970                 printf("cli_write failed: %s\n", nt_errstr(status));
7971                 goto out;
7972         }
7973
7974         cli_close(cli1, fnum1);
7975
7976         /* Now create a hardlink. */
7977         status = cli_posix_hardlink(cli1, fname, hname);
7978         if (!NT_STATUS_IS_OK(status)) {
7979                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7980                 goto out;
7981         }
7982
7983         /* Now create a symlink. */
7984         status = cli_posix_symlink(cli1, fname, sname);
7985         if (!NT_STATUS_IS_OK(status)) {
7986                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7987                 goto out;
7988         }
7989
7990         /* Open the hardlink for read. */
7991         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7992         if (!NT_STATUS_IS_OK(status)) {
7993                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7994                 goto out;
7995         }
7996
7997         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7998         if (!NT_STATUS_IS_OK(status)) {
7999                 printf("POSIX read of %s failed (%s)\n", hname,
8000                        nt_errstr(status));
8001                 goto out;
8002         } else if (nread != 10) {
8003                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8004                        hname, (unsigned long)nread, 10);
8005                 goto out;
8006         }
8007
8008         if (memcmp(buf, "TEST DATA\n", 10)) {
8009                 printf("invalid data read from hardlink\n");
8010                 goto out;
8011         }
8012
8013         /* Do a POSIX lock/unlock. */
8014         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8015         if (!NT_STATUS_IS_OK(status)) {
8016                 printf("POSIX lock failed %s\n", nt_errstr(status));
8017                 goto out;
8018         }
8019
8020         /* Punch a hole in the locked area. */
8021         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8022         if (!NT_STATUS_IS_OK(status)) {
8023                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8024                 goto out;
8025         }
8026
8027         cli_close(cli1, fnum1);
8028
8029         /* Open the symlink for read - this should fail. A POSIX
8030            client should not be doing opens on a symlink. */
8031         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8032         if (NT_STATUS_IS_OK(status)) {
8033                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8034                 goto out;
8035         }
8036         ok = check_both_error(
8037                 __LINE__, status, ERRDOS, ERRbadpath,
8038                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8039         if (!ok) {
8040                 printf("POSIX open of %s should have failed "
8041                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8042                        "failed with %s instead.\n",
8043                        sname, nt_errstr(status));
8044                 goto out;
8045         }
8046
8047         status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8048         if (!NT_STATUS_IS_OK(status)) {
8049                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8050                 goto out;
8051         }
8052
8053         if (strcmp(target, fname) != 0) {
8054                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8055                         sname, fname, target);
8056                 goto out;
8057         }
8058
8059         status = cli_posix_rmdir(cli1, dname);
8060         if (!NT_STATUS_IS_OK(status)) {
8061                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8062                 goto out;
8063         }
8064
8065         /* Check directory opens with a specific permission. */
8066         status = cli_posix_mkdir(cli1, dname, 0700);
8067         if (!NT_STATUS_IS_OK(status)) {
8068                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8069                 goto out;
8070         }
8071
8072         /* Ensure st_mode == 0700 */
8073         status = cli_posix_stat(cli1, dname, &sbuf);
8074         if (!NT_STATUS_IS_OK(status)) {
8075                 printf("stat failed (%s)\n", nt_errstr(status));
8076                 goto out;
8077         }
8078
8079         if ((sbuf.st_ex_mode & 07777) != 0700) {
8080                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8081                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8082                 goto out;
8083         }
8084
8085         /*
8086          * Now create a Windows file, and attempt a POSIX unlink.
8087          * This should fail with a sharing violation but due to:
8088          *
8089          * [Bug 9571] Unlink after open causes smbd to panic
8090          *
8091          * ensure we've fixed the lock ordering violation.
8092          */
8093
8094         status = cli_ntcreate(cli1, fname_windows, 0,
8095                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8096                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8097                         FILE_CREATE,
8098                         0x0, 0x0, &fnum2, NULL);
8099         if (!NT_STATUS_IS_OK(status)) {
8100                 printf("Windows create of %s failed (%s)\n", fname_windows,
8101                         nt_errstr(status));
8102                 goto out;
8103         }
8104
8105         /* Now try posix_unlink. */
8106         status = cli_posix_unlink(cli1, fname_windows);
8107         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8108                 printf("POSIX unlink of %s should fail "
8109                         "with NT_STATUS_SHARING_VIOLATION "
8110                         "got %s instead !\n",
8111                         fname_windows,
8112                         nt_errstr(status));
8113                 goto out;
8114         }
8115
8116         cli_close(cli1, fnum2);
8117
8118         printf("Simple POSIX open test passed\n");
8119         correct = true;
8120
8121   out:
8122
8123         if (fnum1 != (uint16_t)-1) {
8124                 cli_close(cli1, fnum1);
8125                 fnum1 = (uint16_t)-1;
8126         }
8127
8128         if (fnum2 != (uint16_t)-1) {
8129                 cli_close(cli1, fnum2);
8130                 fnum2 = (uint16_t)-1;
8131         }
8132
8133         cli_setatr(cli1, sname, 0, 0);
8134         cli_posix_unlink(cli1, sname);
8135         cli_setatr(cli1, hname, 0, 0);
8136         cli_posix_unlink(cli1, hname);
8137         cli_setatr(cli1, fname, 0, 0);
8138         cli_posix_unlink(cli1, fname);
8139         cli_setatr(cli1, dname, 0, 0);
8140         cli_posix_rmdir(cli1, dname);
8141         cli_setatr(cli1, fname_windows, 0, 0);
8142         cli_posix_unlink(cli1, fname_windows);
8143
8144         if (!torture_close_connection(cli1)) {
8145                 correct = false;
8146         }
8147
8148         return correct;
8149 }
8150
8151 /*
8152   Test POSIX and Windows ACLs are rejected on symlinks.
8153  */
8154 static bool run_acl_symlink_test(int dummy)
8155 {
8156         static struct cli_state *cli;
8157         const char *fname = "posix_file";
8158         const char *sname = "posix_symlink";
8159         uint16_t fnum = (uint16_t)-1;
8160         bool correct = false;
8161         NTSTATUS status;
8162         char *posix_acl = NULL;
8163         size_t posix_acl_len = 0;
8164         char *posix_acl_sym = NULL;
8165         size_t posix_acl_len_sym = 0;
8166         struct security_descriptor *sd = NULL;
8167         TALLOC_CTX *frame = NULL;
8168
8169         frame = talloc_stackframe();
8170
8171         printf("Starting acl symlink test\n");
8172
8173         if (!torture_open_connection(&cli, 0)) {
8174                 TALLOC_FREE(frame);
8175                 return false;
8176         }
8177
8178         smbXcli_conn_set_sockopt(cli->conn, sockops);
8179
8180         status = torture_setup_unix_extensions(cli);
8181         if (!NT_STATUS_IS_OK(status)) {
8182                 TALLOC_FREE(frame);
8183                 return false;
8184         }
8185
8186         cli_setatr(cli, fname, 0, 0);
8187         cli_posix_unlink(cli, fname);
8188         cli_setatr(cli, sname, 0, 0);
8189         cli_posix_unlink(cli, sname);
8190
8191         status = cli_ntcreate(cli,
8192                         fname,
8193                         0,
8194                         READ_CONTROL_ACCESS,
8195                         0,
8196                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8197                         FILE_CREATE,
8198                         0x0,
8199                         0x0,
8200                         &fnum,
8201                         NULL);
8202
8203         if (!NT_STATUS_IS_OK(status)) {
8204                 printf("cli_ntcreate of %s failed (%s)\n",
8205                         fname,
8206                         nt_errstr(status));
8207                 goto out;
8208         }
8209
8210         /* Get the Windows ACL on the file. */
8211         status = cli_query_secdesc(cli,
8212                                 fnum,
8213                                 frame,
8214                                 &sd);
8215         if (!NT_STATUS_IS_OK(status)) {
8216                 printf("cli_query_secdesc failed (%s)\n",
8217                         nt_errstr(status));
8218                 goto out;
8219         }
8220
8221         /* Get the POSIX ACL on the file. */
8222         status = cli_posix_getacl(cli,
8223                                 fname,
8224                                 frame,
8225                                 &posix_acl_len,
8226                                 &posix_acl);
8227
8228         if (!NT_STATUS_IS_OK(status)) {
8229                 printf("cli_posix_getacl failed (%s)\n",
8230                         nt_errstr(status));
8231                 goto out;
8232         }
8233
8234         status = cli_close(cli, fnum);
8235         if (!NT_STATUS_IS_OK(status)) {
8236                 printf("close failed (%s)\n", nt_errstr(status));
8237                 goto out;
8238         }
8239         fnum = (uint16_t)-1;
8240
8241         /* Now create a symlink. */
8242         status = cli_posix_symlink(cli, fname, sname);
8243         if (!NT_STATUS_IS_OK(status)) {
8244                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8245                         sname,
8246                         fname,
8247                         nt_errstr(status));
8248                 goto out;
8249         }
8250
8251         /* Open a handle on the symlink for SD set/get should fail. */
8252         status = cli_ntcreate(cli,
8253                         sname,
8254                         0,
8255                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8256                         0,
8257                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8258                         FILE_OPEN,
8259                         0x0,
8260                         0x0,
8261                         &fnum,
8262                         NULL);
8263
8264         if (NT_STATUS_IS_OK(status)) {
8265                 printf("Symlink open for getsd/setsd of %s "
8266                         "succeeded (should fail)\n",
8267                         sname);
8268                 goto out;
8269         }
8270
8271         /* Try a stat-open on the symlink, should also fail. */
8272         status = cli_ntcreate(cli,
8273                         sname,
8274                         0,
8275                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8276                         0,
8277                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8278                         FILE_OPEN,
8279                         0x0,
8280                         0x0,
8281                         &fnum,
8282                         NULL);
8283
8284         if (NT_STATUS_IS_OK(status)) {
8285                 printf("Stat-open of symlink succeeded (should fail)\n");
8286                 goto out;
8287         }
8288
8289         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8290         status = cli_posix_getacl(cli,
8291                                 sname,
8292                                 frame,
8293                                 &posix_acl_len_sym,
8294                                 &posix_acl_sym);
8295
8296         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8297                 printf("cli_posix_getacl on a symlink gave %s. "
8298                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8299                         nt_errstr(status));
8300                 goto out;
8301         }
8302
8303         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8304         status = cli_posix_setacl(cli,
8305                                 sname,
8306                                 posix_acl,
8307                                 posix_acl_len);
8308
8309         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8310                 printf("cli_posix_setacl on a symlink gave %s. "
8311                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8312                         nt_errstr(status));
8313                 goto out;
8314         }
8315
8316         printf("ACL symlink test passed\n");
8317         correct = true;
8318
8319   out:
8320
8321         if (fnum != (uint16_t)-1) {
8322                 cli_close(cli, fnum);
8323                 fnum = (uint16_t)-1;
8324         }
8325
8326         cli_setatr(cli, sname, 0, 0);
8327         cli_posix_unlink(cli, sname);
8328         cli_setatr(cli, fname, 0, 0);
8329         cli_posix_unlink(cli, fname);
8330
8331         if (!torture_close_connection(cli)) {
8332                 correct = false;
8333         }
8334
8335         TALLOC_FREE(frame);
8336         return correct;
8337 }
8338
8339 /*
8340   Test POSIX can delete a file containing streams.
8341  */
8342 static bool run_posix_stream_delete(int dummy)
8343 {
8344         struct cli_state *cli1 = NULL;
8345         struct cli_state *cli2 = NULL;
8346         const char *fname = "streamfile";
8347         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8348         uint16_t fnum1 = (uint16_t)-1;
8349         bool correct = false;
8350         NTSTATUS status;
8351         TALLOC_CTX *frame = NULL;
8352
8353         frame = talloc_stackframe();
8354
8355         printf("Starting POSIX stream delete test\n");
8356
8357         if (!torture_open_connection(&cli1, 0) ||
8358                         !torture_open_connection(&cli2, 1)) {
8359                 TALLOC_FREE(frame);
8360                 return false;
8361         }
8362
8363         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8364         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8365
8366         status = torture_setup_unix_extensions(cli2);
8367         if (!NT_STATUS_IS_OK(status)) {
8368                 goto out;
8369         }
8370
8371         cli_setatr(cli1, fname, 0, 0);
8372         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8373
8374         /* Create the file. */
8375         status = cli_ntcreate(cli1,
8376                         fname,
8377                         0,
8378                         READ_CONTROL_ACCESS,
8379                         0,
8380                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8381                         FILE_CREATE,
8382                         0x0,
8383                         0x0,
8384                         &fnum1,
8385                         NULL);
8386
8387         if (!NT_STATUS_IS_OK(status)) {
8388                 printf("cli_ntcreate of %s failed (%s)\n",
8389                         fname,
8390                         nt_errstr(status));
8391                 goto out;
8392         }
8393
8394         status = cli_close(cli1, fnum1);
8395         if (!NT_STATUS_IS_OK(status)) {
8396                 printf("cli_close of %s failed (%s)\n",
8397                         fname,
8398                         nt_errstr(status));
8399                 goto out;
8400         }
8401         fnum1 = (uint16_t)-1;
8402
8403         /* Now create the stream. */
8404         status = cli_ntcreate(cli1,
8405                         stream_fname,
8406                         0,
8407                         FILE_WRITE_DATA,
8408                         0,
8409                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8410                         FILE_CREATE,
8411                         0x0,
8412                         0x0,
8413                         &fnum1,
8414                         NULL);
8415
8416         if (!NT_STATUS_IS_OK(status)) {
8417                 printf("cli_ntcreate of %s failed (%s)\n",
8418                         stream_fname,
8419                         nt_errstr(status));
8420                 goto out;
8421         }
8422
8423         /* Leave the stream handle open... */
8424
8425         /* POSIX unlink should fail. */
8426         status = cli_posix_unlink(cli2, fname);
8427         if (NT_STATUS_IS_OK(status)) {
8428                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8429                         fname);
8430                 goto out;
8431         }
8432
8433         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8434                 printf("cli_posix_unlink of %s failed with (%s) "
8435                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8436                         fname,
8437                         nt_errstr(status));
8438                 goto out;
8439         }
8440
8441         /* Close the stream handle. */
8442         status = cli_close(cli1, fnum1);
8443         if (!NT_STATUS_IS_OK(status)) {
8444                 printf("cli_close of %s failed (%s)\n",
8445                         stream_fname,
8446                         nt_errstr(status));
8447                 goto out;
8448         }
8449         fnum1 = (uint16_t)-1;
8450
8451         /* POSIX unlink after stream handle closed should succeed. */
8452         status = cli_posix_unlink(cli2, fname);
8453         if (!NT_STATUS_IS_OK(status)) {
8454                 printf("cli_posix_unlink of %s failed (%s)\n",
8455                         fname,
8456                         nt_errstr(status));
8457                 goto out;
8458         }
8459
8460         printf("POSIX stream delete test passed\n");
8461         correct = true;
8462
8463   out:
8464
8465         if (fnum1 != (uint16_t)-1) {
8466                 cli_close(cli1, fnum1);
8467                 fnum1 = (uint16_t)-1;
8468         }
8469
8470         cli_setatr(cli1, fname, 0, 0);
8471         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8472
8473         if (!torture_close_connection(cli1)) {
8474                 correct = false;
8475         }
8476         if (!torture_close_connection(cli2)) {
8477                 correct = false;
8478         }
8479
8480         TALLOC_FREE(frame);
8481         return correct;
8482 }
8483
8484 /*
8485   Test setting EA's are rejected on symlinks.
8486  */
8487 static bool run_ea_symlink_test(int dummy)
8488 {
8489         static struct cli_state *cli;
8490         const char *fname = "posix_file_ea";
8491         const char *sname = "posix_symlink_ea";
8492         const char *ea_name = "testea_name";
8493         const char *ea_value = "testea_value";
8494         uint16_t fnum = (uint16_t)-1;
8495         bool correct = false;
8496         NTSTATUS status;
8497         size_t i, num_eas;
8498         struct ea_struct *eas = NULL;
8499         TALLOC_CTX *frame = NULL;
8500
8501         frame = talloc_stackframe();
8502
8503         printf("Starting EA symlink test\n");
8504
8505         if (!torture_open_connection(&cli, 0)) {
8506                 TALLOC_FREE(frame);
8507                 return false;
8508         }
8509
8510         smbXcli_conn_set_sockopt(cli->conn, sockops);
8511
8512         status = torture_setup_unix_extensions(cli);
8513         if (!NT_STATUS_IS_OK(status)) {
8514                 TALLOC_FREE(frame);
8515                 return false;
8516         }
8517
8518         cli_setatr(cli, fname, 0, 0);
8519         cli_posix_unlink(cli, fname);
8520         cli_setatr(cli, sname, 0, 0);
8521         cli_posix_unlink(cli, sname);
8522
8523         status = cli_ntcreate(cli,
8524                         fname,
8525                         0,
8526                         READ_CONTROL_ACCESS,
8527                         0,
8528                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8529                         FILE_CREATE,
8530                         0x0,
8531                         0x0,
8532                         &fnum,
8533                         NULL);
8534
8535         if (!NT_STATUS_IS_OK(status)) {
8536                 printf("cli_ntcreate of %s failed (%s)\n",
8537                         fname,
8538                         nt_errstr(status));
8539                 goto out;
8540         }
8541
8542         status = cli_close(cli, fnum);
8543         if (!NT_STATUS_IS_OK(status)) {
8544                 printf("close failed (%s)\n",
8545                         nt_errstr(status));
8546                 goto out;
8547         }
8548         fnum = (uint16_t)-1;
8549
8550         /* Set an EA on the path. */
8551         status = cli_set_ea_path(cli,
8552                                 fname,
8553                                 ea_name,
8554                                 ea_value,
8555                                 strlen(ea_value)+1);
8556
8557         if (!NT_STATUS_IS_OK(status)) {
8558                 printf("cli_set_ea_path failed (%s)\n",
8559                         nt_errstr(status));
8560                 goto out;
8561         }
8562
8563         /* Now create a symlink. */
8564         status = cli_posix_symlink(cli, fname, sname);
8565         if (!NT_STATUS_IS_OK(status)) {
8566                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8567                         sname,
8568                         fname,
8569                         nt_errstr(status));
8570                 goto out;
8571         }
8572
8573         /* Get the EA list on the path. Should return value set. */
8574         status = cli_get_ea_list_path(cli,
8575                                 fname,
8576                                 frame,
8577                                 &num_eas,
8578                                 &eas);
8579
8580         if (!NT_STATUS_IS_OK(status)) {
8581                 printf("cli_get_ea_list_path failed (%s)\n",
8582                         nt_errstr(status));
8583                 goto out;
8584         }
8585
8586         /* Ensure the EA we set is there. */
8587         for (i=0; i<num_eas; i++) {
8588                 if (strcmp(eas[i].name, ea_name) == 0 &&
8589                                 eas[i].value.length == strlen(ea_value)+1 &&
8590                                 memcmp(eas[i].value.data,
8591                                         ea_value,
8592                                         eas[i].value.length) == 0) {
8593                         break;
8594                 }
8595         }
8596
8597         if (i == num_eas) {
8598                 printf("Didn't find EA on pathname %s\n",
8599                         fname);
8600                 goto out;
8601         }
8602
8603         num_eas = 0;
8604         TALLOC_FREE(eas);
8605
8606         /* Get the EA list on the symlink. Should return empty list. */
8607         status = cli_get_ea_list_path(cli,
8608                                 sname,
8609                                 frame,
8610                                 &num_eas,
8611                                 &eas);
8612
8613         if (!NT_STATUS_IS_OK(status)) {
8614                 printf("cli_get_ea_list_path failed (%s)\n",
8615                         nt_errstr(status));
8616                 goto out;
8617         }
8618
8619         if (num_eas != 0) {
8620                 printf("cli_get_ea_list_path failed (%s)\n",
8621                         nt_errstr(status));
8622                 goto out;
8623         }
8624
8625         /* Set an EA on the symlink. Should fail. */
8626         status = cli_set_ea_path(cli,
8627                                 sname,
8628                                 ea_name,
8629                                 ea_value,
8630                                 strlen(ea_value)+1);
8631
8632         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8633                 printf("cli_set_ea_path on a symlink gave %s. "
8634                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8635                         nt_errstr(status));
8636                 goto out;
8637         }
8638
8639         printf("EA symlink test passed\n");
8640         correct = true;
8641
8642   out:
8643
8644         if (fnum != (uint16_t)-1) {
8645                 cli_close(cli, fnum);
8646                 fnum = (uint16_t)-1;
8647         }
8648
8649         cli_setatr(cli, sname, 0, 0);
8650         cli_posix_unlink(cli, sname);
8651         cli_setatr(cli, fname, 0, 0);
8652         cli_posix_unlink(cli, fname);
8653
8654         if (!torture_close_connection(cli)) {
8655                 correct = false;
8656         }
8657
8658         TALLOC_FREE(frame);
8659         return correct;
8660 }
8661
8662 /*
8663   Test POSIX locks are OFD-locks.
8664  */
8665 static bool run_posix_ofd_lock_test(int dummy)
8666 {
8667         static struct cli_state *cli;
8668         const char *fname = "posix_file";
8669         uint16_t fnum1 = (uint16_t)-1;
8670         uint16_t fnum2 = (uint16_t)-1;
8671         bool correct = false;
8672         NTSTATUS status;
8673         TALLOC_CTX *frame = NULL;
8674
8675         frame = talloc_stackframe();
8676
8677         printf("Starting POSIX ofd-lock test\n");
8678
8679         if (!torture_open_connection(&cli, 0)) {
8680                 TALLOC_FREE(frame);
8681                 return false;
8682         }
8683
8684         smbXcli_conn_set_sockopt(cli->conn, sockops);
8685
8686         status = torture_setup_unix_extensions(cli);
8687         if (!NT_STATUS_IS_OK(status)) {
8688                 TALLOC_FREE(frame);
8689                 return false;
8690         }
8691
8692         cli_setatr(cli, fname, 0, 0);
8693         cli_posix_unlink(cli, fname);
8694
8695         /* Open the file twice. */
8696         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8697                                 0600, &fnum1);
8698         if (!NT_STATUS_IS_OK(status)) {
8699                 printf("First POSIX open of %s failed\n", fname);
8700                 goto out;
8701         }
8702
8703         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8704         if (!NT_STATUS_IS_OK(status)) {
8705                 printf("First POSIX open of %s failed\n", fname);
8706                 goto out;
8707         }
8708
8709         /* Set a 0-50 lock on fnum1. */
8710         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8711         if (!NT_STATUS_IS_OK(status)) {
8712                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8713                 goto out;
8714         }
8715
8716         /* Set a 60-100 lock on fnum2. */
8717         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8718         if (!NT_STATUS_IS_OK(status)) {
8719                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8720                 goto out;
8721         }
8722
8723         /* close fnum1 - 0-50 lock should go away. */
8724         status = cli_close(cli, fnum1);
8725         if (!NT_STATUS_IS_OK(status)) {
8726                 printf("close failed (%s)\n",
8727                         nt_errstr(status));
8728                 goto out;
8729         }
8730         fnum1 = (uint16_t)-1;
8731
8732         /* Change the lock context. */
8733         cli_setpid(cli, cli_getpid(cli) + 1);
8734
8735         /* Re-open fnum1. */
8736         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8737         if (!NT_STATUS_IS_OK(status)) {
8738                 printf("Third POSIX open of %s failed\n", fname);
8739                 goto out;
8740         }
8741
8742         /* 60-100 lock should still be there. */
8743         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8744         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8745                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8746                 goto out;
8747         }
8748
8749         /* 0-50 lock should be gone. */
8750         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8751         if (!NT_STATUS_IS_OK(status)) {
8752                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8753                 goto out;
8754         }
8755
8756         printf("POSIX OFD lock test passed\n");
8757         correct = true;
8758
8759   out:
8760
8761         if (fnum1 != (uint16_t)-1) {
8762                 cli_close(cli, fnum1);
8763                 fnum1 = (uint16_t)-1;
8764         }
8765         if (fnum2 != (uint16_t)-1) {
8766                 cli_close(cli, fnum2);
8767                 fnum2 = (uint16_t)-1;
8768         }
8769
8770         cli_setatr(cli, fname, 0, 0);
8771         cli_posix_unlink(cli, fname);
8772
8773         if (!torture_close_connection(cli)) {
8774                 correct = false;
8775         }
8776
8777         TALLOC_FREE(frame);
8778         return correct;
8779 }
8780
8781 struct posix_blocking_state {
8782         struct tevent_context *ev;
8783         struct cli_state *cli1;
8784         uint16_t fnum1;
8785         struct cli_state *cli2;
8786         uint16_t fnum2;
8787         bool gotblocked;
8788         bool gotecho;
8789 };
8790
8791 static void posix_blocking_locked(struct tevent_req *subreq);
8792 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8793 static void posix_blocking_gotecho(struct tevent_req *subreq);
8794 static void posix_blocking_unlocked(struct tevent_req *subreq);
8795
8796 static struct tevent_req *posix_blocking_send(
8797         TALLOC_CTX *mem_ctx,
8798         struct tevent_context *ev,
8799         struct cli_state *cli1,
8800         uint16_t fnum1,
8801         struct cli_state *cli2,
8802         uint16_t fnum2)
8803 {
8804         struct tevent_req *req = NULL, *subreq = NULL;
8805         struct posix_blocking_state *state = NULL;
8806
8807         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8808         if (req == NULL) {
8809                 return NULL;
8810         }
8811         state->ev = ev;
8812         state->cli1 = cli1;
8813         state->fnum1 = fnum1;
8814         state->cli2 = cli2;
8815         state->fnum2 = fnum2;
8816
8817         subreq = cli_posix_lock_send(
8818                 state,
8819                 state->ev,
8820                 state->cli1,
8821                 state->fnum1,
8822                 0,
8823                 1,
8824                 false,
8825                 WRITE_LOCK);
8826         if (tevent_req_nomem(subreq, req)) {
8827                 return tevent_req_post(req, ev);
8828         }
8829         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8830         return req;
8831 }
8832
8833 static void posix_blocking_locked(struct tevent_req *subreq)
8834 {
8835         struct tevent_req *req = tevent_req_callback_data(
8836                 subreq, struct tevent_req);
8837         struct posix_blocking_state *state = tevent_req_data(
8838                 req, struct posix_blocking_state);
8839         NTSTATUS status;
8840
8841         status = cli_posix_lock_recv(subreq);
8842         TALLOC_FREE(subreq);
8843         if (tevent_req_nterror(req, status)) {
8844                 return;
8845         }
8846
8847         subreq = cli_posix_lock_send(
8848                 state,
8849                 state->ev,
8850                 state->cli2,
8851                 state->fnum2,
8852                 0,
8853                 1,
8854                 true,
8855                 WRITE_LOCK);
8856         if (tevent_req_nomem(subreq, req)) {
8857                 return;
8858         }
8859         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8860
8861         /* Make sure the blocking request is delivered */
8862         subreq = cli_echo_send(
8863                 state,
8864                 state->ev,
8865                 state->cli2,
8866                 1,
8867                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8868         if (tevent_req_nomem(subreq, req)) {
8869                 return;
8870         }
8871         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8872 }
8873
8874 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8875 {
8876         struct tevent_req *req = tevent_req_callback_data(
8877                 subreq, struct tevent_req);
8878         struct posix_blocking_state *state = tevent_req_data(
8879                 req, struct posix_blocking_state);
8880         NTSTATUS status;
8881
8882         status = cli_posix_lock_recv(subreq);
8883         TALLOC_FREE(subreq);
8884         if (tevent_req_nterror(req, status)) {
8885                 return;
8886         }
8887         if (!state->gotecho) {
8888                 printf("blocked req got through before echo\n");
8889                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8890                 return;
8891         }
8892         tevent_req_done(req);
8893 }
8894
8895 static void posix_blocking_gotecho(struct tevent_req *subreq)
8896 {
8897         struct tevent_req *req = tevent_req_callback_data(
8898                 subreq, struct tevent_req);
8899         struct posix_blocking_state *state = tevent_req_data(
8900                 req, struct posix_blocking_state);
8901         NTSTATUS status;
8902
8903         status = cli_echo_recv(subreq);
8904         TALLOC_FREE(subreq);
8905         if (tevent_req_nterror(req, status)) {
8906                 return;
8907         }
8908         if (state->gotblocked) {
8909                 printf("blocked req got through before echo\n");
8910                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8911                 return;
8912         }
8913         state->gotecho = true;
8914
8915         subreq = cli_posix_lock_send(
8916                 state,
8917                 state->ev,
8918                 state->cli1,
8919                 state->fnum1,
8920                 0,
8921                 1,
8922                 false,
8923                 UNLOCK_LOCK);
8924         if (tevent_req_nomem(subreq, req)) {
8925                 return;
8926         }
8927         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8928 }
8929
8930 static void posix_blocking_unlocked(struct tevent_req *subreq)
8931 {
8932         struct tevent_req *req = tevent_req_callback_data(
8933                 subreq, struct tevent_req);
8934         NTSTATUS status;
8935
8936         status = cli_posix_lock_recv(subreq);
8937         TALLOC_FREE(subreq);
8938         if (tevent_req_nterror(req, status)) {
8939                 return;
8940         }
8941         /* tevent_req_done in posix_blocking_gotlocked */
8942 }
8943
8944 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8945 {
8946         return tevent_req_simple_recv_ntstatus(req);
8947 }
8948
8949 static bool run_posix_blocking_lock(int dummy)
8950 {
8951         struct tevent_context *ev = NULL;
8952         struct cli_state *cli1 = NULL, *cli2 = NULL;
8953         const char *fname = "posix_blocking";
8954         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8955         struct tevent_req *req = NULL;
8956         NTSTATUS status;
8957         bool ret = false;
8958         bool ok;
8959
8960         printf("Starting posix blocking lock test\n");
8961
8962         ev = samba_tevent_context_init(NULL);
8963         if (ev == NULL) {
8964                 return false;
8965         }
8966
8967         ok = torture_open_connection(&cli1, 0);
8968         if (!ok) {
8969                 goto fail;
8970         }
8971         ok = torture_open_connection(&cli2, 0);
8972         if (!ok) {
8973                 goto fail;
8974         }
8975
8976         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8977
8978         status = torture_setup_unix_extensions(cli1);
8979         if (!NT_STATUS_IS_OK(status)) {
8980                 return false;
8981         }
8982
8983         status = torture_setup_unix_extensions(cli2);
8984         if (!NT_STATUS_IS_OK(status)) {
8985                 return false;
8986         }
8987
8988         cli_setatr(cli1, fname, 0, 0);
8989         cli_posix_unlink(cli1, fname);
8990
8991         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8992                                 0600, &fnum1);
8993         if (!NT_STATUS_IS_OK(status)) {
8994                 printf("First POSIX open of %s failed: %s\n",
8995                        fname,
8996                        nt_errstr(status));
8997                 goto fail;
8998         }
8999
9000         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9001         if (!NT_STATUS_IS_OK(status)) {
9002                 printf("Second POSIX open of %s failed: %s\n",
9003                        fname,
9004                        nt_errstr(status));
9005                 goto fail;
9006         }
9007
9008         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9009         if (req == NULL) {
9010                 printf("cli_posix_blocking failed\n");
9011                 goto fail;
9012         }
9013
9014         ok = tevent_req_poll_ntstatus(req, ev, &status);
9015         if (!ok) {
9016                 printf("tevent_req_poll_ntstatus failed: %s\n",
9017                        nt_errstr(status));
9018                 goto fail;
9019         }
9020         status = posix_blocking_recv(req);
9021         TALLOC_FREE(req);
9022         if (!NT_STATUS_IS_OK(status)) {
9023                 printf("posix_blocking_recv returned %s\n",
9024                        nt_errstr(status));
9025                 goto fail;
9026         }
9027
9028         ret = true;
9029 fail:
9030
9031         if (fnum1 != UINT16_MAX) {
9032                 cli_close(cli1, fnum1);
9033                 fnum1 = UINT16_MAX;
9034         }
9035         if (fnum2 != UINT16_MAX) {
9036                 cli_close(cli2, fnum2);
9037                 fnum2 = UINT16_MAX;
9038         }
9039
9040         if (cli1 != NULL) {
9041                 cli_setatr(cli1, fname, 0, 0);
9042                 cli_posix_unlink(cli1, fname);
9043         }
9044
9045         ok = true;
9046
9047         if (cli1 != NULL) {
9048                 ok &= torture_close_connection(cli1);
9049                 cli1 = NULL;
9050         }
9051         if (cli2 != NULL) {
9052                 ok &= torture_close_connection(cli2);
9053                 cli2 = NULL;
9054         }
9055
9056         if (!ok) {
9057                 ret = false;
9058         }
9059         TALLOC_FREE(ev);
9060         return ret;
9061 }
9062
9063 /*
9064   Test POSIX mkdir is case-sensitive.
9065  */
9066 static bool run_posix_mkdir_test(int dummy)
9067 {
9068         static struct cli_state *cli;
9069         const char *fname_foo = "POSIX_foo";
9070         const char *fname_foo_Foo = "POSIX_foo/Foo";
9071         const char *fname_foo_foo = "POSIX_foo/foo";
9072         const char *fname_Foo = "POSIX_Foo";
9073         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9074         const char *fname_Foo_foo = "POSIX_Foo/foo";
9075         bool correct = false;
9076         NTSTATUS status;
9077         TALLOC_CTX *frame = NULL;
9078         uint16_t fnum = (uint16_t)-1;
9079
9080         frame = talloc_stackframe();
9081
9082         printf("Starting POSIX mkdir test\n");
9083
9084         if (!torture_open_connection(&cli, 0)) {
9085                 TALLOC_FREE(frame);
9086                 return false;
9087         }
9088
9089         smbXcli_conn_set_sockopt(cli->conn, sockops);
9090
9091         status = torture_setup_unix_extensions(cli);
9092         if (!NT_STATUS_IS_OK(status)) {
9093                 TALLOC_FREE(frame);
9094                 return false;
9095         }
9096
9097         cli_posix_rmdir(cli, fname_foo_foo);
9098         cli_posix_rmdir(cli, fname_foo_Foo);
9099         cli_posix_rmdir(cli, fname_foo);
9100
9101         cli_posix_rmdir(cli, fname_Foo_foo);
9102         cli_posix_rmdir(cli, fname_Foo_Foo);
9103         cli_posix_rmdir(cli, fname_Foo);
9104
9105         /*
9106          * Create a file POSIX_foo then try
9107          * and use it in a directory path by
9108          * doing mkdir POSIX_foo/bar.
9109          * The mkdir should fail with
9110          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9111          */
9112
9113         status = cli_posix_open(cli,
9114                         fname_foo,
9115                         O_RDWR|O_CREAT,
9116                         0666,
9117                         &fnum);
9118         if (!NT_STATUS_IS_OK(status)) {
9119                 printf("cli_posix_open of %s failed error %s\n",
9120                         fname_foo,
9121                         nt_errstr(status));
9122                 goto out;
9123         }
9124
9125         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9126         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9127                 printf("cli_posix_mkdir of %s should fail with "
9128                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9129                         "%s instead\n",
9130                         fname_foo_foo,
9131                         nt_errstr(status));
9132                 goto out;
9133         }
9134
9135         status = cli_close(cli, fnum);
9136         if (!NT_STATUS_IS_OK(status)) {
9137                 printf("cli_close failed %s\n", nt_errstr(status));
9138                 goto out;
9139         }
9140         fnum = (uint16_t)-1;
9141
9142         status = cli_posix_unlink(cli, fname_foo);
9143         if (!NT_STATUS_IS_OK(status)) {
9144                 printf("cli_posix_unlink of %s failed error %s\n",
9145                         fname_foo,
9146                         nt_errstr(status));
9147                 goto out;
9148         }
9149
9150         /*
9151          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9152          * posix_open, posix_unlink, on
9153          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9154          * not silently create POSIX_foo/foo.
9155          */
9156
9157         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9158         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9159                 printf("cli_posix_mkdir of %s should fail with "
9160                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9161                         "%s instead\n",
9162                         fname_foo_foo,
9163                         nt_errstr(status));
9164                 goto out;
9165         }
9166
9167         status = cli_posix_rmdir(cli, fname_foo_foo);
9168         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9169                 printf("cli_posix_rmdir of %s should fail with "
9170                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9171                         "%s instead\n",
9172                         fname_foo_foo,
9173                         nt_errstr(status));
9174                 goto out;
9175         }
9176
9177         status = cli_posix_open(cli,
9178                         fname_foo_foo,
9179                         O_RDWR|O_CREAT,
9180                         0666,
9181                         &fnum);
9182         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9183                 printf("cli_posix_open of %s should fail with "
9184                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9185                         "%s instead\n",
9186                         fname_foo_foo,
9187                         nt_errstr(status));
9188                 goto out;
9189         }
9190
9191         status = cli_posix_unlink(cli, fname_foo_foo);
9192         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9193                 printf("cli_posix_unlink of %s should fail with "
9194                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9195                         "%s instead\n",
9196                         fname_foo_foo,
9197                         nt_errstr(status));
9198                 goto out;
9199         }
9200
9201         status = cli_posix_mkdir(cli, fname_foo, 0777);
9202         if (!NT_STATUS_IS_OK(status)) {
9203                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9204                 goto out;
9205         }
9206
9207         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9208         if (!NT_STATUS_IS_OK(status)) {
9209                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9210                 goto out;
9211         }
9212
9213         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9214         if (!NT_STATUS_IS_OK(status)) {
9215                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9216                 goto out;
9217         }
9218
9219         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9220         if (!NT_STATUS_IS_OK(status)) {
9221                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9222                 goto out;
9223         }
9224
9225         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9226         if (!NT_STATUS_IS_OK(status)) {
9227                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9228                 goto out;
9229         }
9230
9231         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9232         if (!NT_STATUS_IS_OK(status)) {
9233                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9234                 goto out;
9235         }
9236
9237         printf("POSIX mkdir test passed\n");
9238         correct = true;
9239
9240   out:
9241
9242         if (fnum != (uint16_t)-1) {
9243                 cli_close(cli, fnum);
9244                 fnum = (uint16_t)-1;
9245         }
9246
9247         cli_posix_rmdir(cli, fname_foo_foo);
9248         cli_posix_rmdir(cli, fname_foo_Foo);
9249         cli_posix_rmdir(cli, fname_foo);
9250
9251         cli_posix_rmdir(cli, fname_Foo_foo);
9252         cli_posix_rmdir(cli, fname_Foo_Foo);
9253         cli_posix_rmdir(cli, fname_Foo);
9254
9255         if (!torture_close_connection(cli)) {
9256                 correct = false;
9257         }
9258
9259         TALLOC_FREE(frame);
9260         return correct;
9261 }
9262
9263 struct posix_acl_oplock_state {
9264         struct tevent_context *ev;
9265         struct cli_state *cli;
9266         bool *got_break;
9267         bool *acl_ret;
9268         NTSTATUS status;
9269 };
9270
9271 static void posix_acl_oplock_got_break(struct tevent_req *req)
9272 {
9273         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9274                 req, struct posix_acl_oplock_state);
9275         uint16_t fnum;
9276         uint8_t level;
9277         NTSTATUS status;
9278
9279         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9280         TALLOC_FREE(req);
9281         if (!NT_STATUS_IS_OK(status)) {
9282                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9283                        nt_errstr(status));
9284                 return;
9285         }
9286         *state->got_break = true;
9287
9288         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9289                                   NO_OPLOCK);
9290         if (req == NULL) {
9291                 printf("cli_oplock_ack_send failed\n");
9292                 return;
9293         }
9294 }
9295
9296 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9297 {
9298         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9299                 req, struct posix_acl_oplock_state);
9300         size_t ret_size = 0;
9301         char *ret_data = NULL;
9302
9303         state->status = cli_posix_getacl_recv(req,
9304                         state,
9305                         &ret_size,
9306                         &ret_data);
9307
9308         if (!NT_STATUS_IS_OK(state->status)) {
9309                 printf("cli_posix_getacl_recv returned %s\n",
9310                         nt_errstr(state->status));
9311         }
9312         *state->acl_ret = true;
9313 }
9314
9315 static bool run_posix_acl_oplock_test(int dummy)
9316 {
9317         struct tevent_context *ev;
9318         struct cli_state *cli1, *cli2;
9319         struct tevent_req *oplock_req, *getacl_req;
9320         const char *fname = "posix_acl_oplock";
9321         uint16_t fnum;
9322         int saved_use_oplocks = use_oplocks;
9323         NTSTATUS status;
9324         bool correct = true;
9325         bool got_break = false;
9326         bool acl_ret = false;
9327
9328         struct posix_acl_oplock_state *state;
9329
9330         printf("starting posix_acl_oplock test\n");
9331
9332         if (!torture_open_connection(&cli1, 0)) {
9333                 use_level_II_oplocks = false;
9334                 use_oplocks = saved_use_oplocks;
9335                 return false;
9336         }
9337
9338         if (!torture_open_connection(&cli2, 1)) {
9339                 use_level_II_oplocks = false;
9340                 use_oplocks = saved_use_oplocks;
9341                 return false;
9342         }
9343
9344         /* Setup posix on cli2 only. */
9345         status = torture_setup_unix_extensions(cli2);
9346         if (!NT_STATUS_IS_OK(status)) {
9347                 return false;
9348         }
9349
9350         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9351         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9352
9353         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9354
9355         /* Create the file on the Windows connection. */
9356         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9357                           &fnum);
9358         if (!NT_STATUS_IS_OK(status)) {
9359                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9360                 return false;
9361         }
9362
9363         status = cli_close(cli1, fnum);
9364         if (!NT_STATUS_IS_OK(status)) {
9365                 printf("close1 failed (%s)\n", nt_errstr(status));
9366                 return false;
9367         }
9368
9369         cli1->use_oplocks = true;
9370
9371         /* Open with oplock. */
9372         status = cli_ntcreate(cli1,
9373                         fname,
9374                         0,
9375                         FILE_READ_DATA,
9376                         FILE_ATTRIBUTE_NORMAL,
9377                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9378                         FILE_OPEN,
9379                         0,
9380                         0,
9381                         &fnum,
9382                         NULL);
9383
9384         if (!NT_STATUS_IS_OK(status)) {
9385                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9386                 return false;
9387         }
9388
9389         ev = samba_tevent_context_init(talloc_tos());
9390         if (ev == NULL) {
9391                 printf("tevent_context_init failed\n");
9392                 return false;
9393         }
9394
9395         state = talloc_zero(ev, struct posix_acl_oplock_state);
9396         if (state == NULL) {
9397                 printf("talloc failed\n");
9398                 return false;
9399         }
9400         state->ev = ev;
9401         state->cli = cli1;
9402         state->got_break = &got_break;
9403         state->acl_ret = &acl_ret;
9404
9405         oplock_req = cli_smb_oplock_break_waiter_send(
9406                 talloc_tos(), ev, cli1);
9407         if (oplock_req == NULL) {
9408                 printf("cli_smb_oplock_break_waiter_send failed\n");
9409                 return false;
9410         }
9411         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9412
9413         /* Get ACL on POSIX connection - should break oplock. */
9414         getacl_req = cli_posix_getacl_send(talloc_tos(),
9415                                 ev,
9416                                 cli2,
9417                                 fname);
9418         if (getacl_req == NULL) {
9419                 printf("cli_posix_getacl_send failed\n");
9420                 return false;
9421         }
9422         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9423
9424         while (!got_break || !acl_ret) {
9425                 int ret;
9426                 ret = tevent_loop_once(ev);
9427                 if (ret == -1) {
9428                         printf("tevent_loop_once failed: %s\n",
9429                                strerror(errno));
9430                         return false;
9431                 }
9432         }
9433
9434         if (!NT_STATUS_IS_OK(state->status)) {
9435                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9436                 correct = false;
9437         }
9438
9439         status = cli_close(cli1, fnum);
9440         if (!NT_STATUS_IS_OK(status)) {
9441                 printf("close2 failed (%s)\n", nt_errstr(status));
9442                 correct = false;
9443         }
9444
9445         status = cli_unlink(cli1,
9446                         fname,
9447                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9448         if (!NT_STATUS_IS_OK(status)) {
9449                 printf("unlink failed (%s)\n", nt_errstr(status));
9450                 correct = false;
9451         }
9452
9453         if (!torture_close_connection(cli1)) {
9454                 correct = false;
9455         }
9456         if (!torture_close_connection(cli2)) {
9457                 correct = false;
9458         }
9459
9460         if (!got_break) {
9461                 correct = false;
9462         }
9463
9464         printf("finished posix acl oplock test\n");
9465
9466         return correct;
9467 }
9468
9469 static bool run_posix_acl_shareroot_test(int dummy)
9470 {
9471         struct cli_state *cli;
9472         NTSTATUS status;
9473         bool correct = false;
9474         char *posix_acl = NULL;
9475         size_t posix_acl_len = 0;
9476         uint16_t num_file_acls = 0;
9477         uint16_t num_dir_acls = 0;
9478         uint16_t i;
9479         uint32_t expected_size = 0;
9480         bool got_user = false;
9481         bool got_group = false;
9482         bool got_other = false;
9483         TALLOC_CTX *frame = NULL;
9484
9485         frame = talloc_stackframe();
9486
9487         printf("starting posix_acl_shareroot test\n");
9488
9489         if (!torture_open_connection(&cli, 0)) {
9490                 TALLOC_FREE(frame);
9491                 return false;
9492         }
9493
9494         smbXcli_conn_set_sockopt(cli->conn, sockops);
9495
9496         status = torture_setup_unix_extensions(cli);
9497         if (!NT_STATUS_IS_OK(status)) {
9498                 printf("Failed to setup unix extensions\n");
9499                 goto out;
9500         }
9501
9502         /* Get the POSIX ACL on the root of the share. */
9503         status = cli_posix_getacl(cli,
9504                                 ".",
9505                                 frame,
9506                                 &posix_acl_len,
9507                                 &posix_acl);
9508
9509         if (!NT_STATUS_IS_OK(status)) {
9510                 printf("cli_posix_getacl of '.' failed (%s)\n",
9511                         nt_errstr(status));
9512                 goto out;
9513         }
9514
9515         if (posix_acl_len < 6 ||
9516                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9517                 printf("getfacl ., unknown POSIX acl version %u.\n",
9518                         (unsigned int)CVAL(posix_acl,0) );
9519                 goto out;
9520         }
9521
9522         num_file_acls = SVAL(posix_acl,2);
9523         num_dir_acls = SVAL(posix_acl,4);
9524         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9525                                 SMB_POSIX_ACL_ENTRY_SIZE*
9526                                 (num_file_acls+num_dir_acls);
9527
9528         if (posix_acl_len != expected_size) {
9529                 printf("incorrect POSIX acl buffer size "
9530                         "(should be %u, was %u).\n",
9531                         (unsigned int)expected_size,
9532                         (unsigned int)posix_acl_len);
9533                 goto out;
9534         }
9535
9536         /*
9537          * We don't need to know what the ACL's are
9538          * we just need to know we have at least 3
9539          * file entries (u,g,o).
9540          */
9541
9542         for (i = 0; i < num_file_acls; i++) {
9543                 unsigned char tagtype =
9544                         CVAL(posix_acl,
9545                                 SMB_POSIX_ACL_HEADER_SIZE+
9546                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9547
9548                 switch(tagtype) {
9549                         case SMB_POSIX_ACL_USER_OBJ:
9550                                 got_user = true;
9551                                 break;
9552                         case SMB_POSIX_ACL_GROUP_OBJ:
9553                                 got_group = true;
9554                                 break;
9555                         case SMB_POSIX_ACL_OTHER:
9556                                 got_other = true;
9557                                 break;
9558                         default:
9559                                 break;
9560                 }
9561         }
9562
9563         if (!got_user) {
9564                 printf("Missing user entry\n");
9565                 goto out;
9566         }
9567
9568         if (!got_group) {
9569                 printf("Missing group entry\n");
9570                 goto out;
9571         }
9572
9573         if (!got_other) {
9574                 printf("Missing other entry\n");
9575                 goto out;
9576         }
9577
9578         correct = true;
9579
9580   out:
9581
9582         if (!torture_close_connection(cli)) {
9583                 correct = false;
9584         }
9585
9586         printf("finished posix acl shareroot test\n");
9587         TALLOC_FREE(frame);
9588
9589         return correct;
9590 }
9591
9592 static uint32_t open_attrs_table[] = {
9593                 FILE_ATTRIBUTE_NORMAL,
9594                 FILE_ATTRIBUTE_ARCHIVE,
9595                 FILE_ATTRIBUTE_READONLY,
9596                 FILE_ATTRIBUTE_HIDDEN,
9597                 FILE_ATTRIBUTE_SYSTEM,
9598
9599                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9600                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9601                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9602                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9603                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9604                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9605
9606                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9607                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9608                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9609                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9610 };
9611
9612 struct trunc_open_results {
9613         unsigned int num;
9614         uint32_t init_attr;
9615         uint32_t trunc_attr;
9616         uint32_t result_attr;
9617 };
9618
9619 static struct trunc_open_results attr_results[] = {
9620         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9621         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9622         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9623         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9624         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9625         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9626         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9627         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9628         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9629         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9630         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9631         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9632         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9633         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9634         { 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 },
9635         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9636         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9637         { 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 },
9638         { 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 },
9639         { 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 },
9640         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9641         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9642         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9643         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9644         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9645         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9646 };
9647
9648 static bool run_openattrtest(int dummy)
9649 {
9650         static struct cli_state *cli1;
9651         const char *fname = "\\openattr.file";
9652         uint16_t fnum1;
9653         bool correct = True;
9654         uint32_t attr;
9655         unsigned int i, j, k, l;
9656         NTSTATUS status;
9657
9658         printf("starting open attr test\n");
9659
9660         if (!torture_open_connection(&cli1, 0)) {
9661                 return False;
9662         }
9663
9664         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9665
9666         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9667                 cli_setatr(cli1, fname, 0, 0);
9668                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9669
9670                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9671                                        open_attrs_table[i], FILE_SHARE_NONE,
9672                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9673                 if (!NT_STATUS_IS_OK(status)) {
9674                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9675                         return False;
9676                 }
9677
9678                 status = cli_close(cli1, fnum1);
9679                 if (!NT_STATUS_IS_OK(status)) {
9680                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9681                         return False;
9682                 }
9683
9684                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9685                         status = cli_ntcreate(cli1, fname, 0,
9686                                               FILE_READ_DATA|FILE_WRITE_DATA,
9687                                               open_attrs_table[j],
9688                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9689                                               0, 0, &fnum1, NULL);
9690                         if (!NT_STATUS_IS_OK(status)) {
9691                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9692                                         if (attr_results[l].num == k) {
9693                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9694                                                                 k, open_attrs_table[i],
9695                                                                 open_attrs_table[j],
9696                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9697                                                 correct = False;
9698                                         }
9699                                 }
9700
9701                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9702                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9703                                                         k, open_attrs_table[i], open_attrs_table[j],
9704                                                         nt_errstr(status));
9705                                         correct = False;
9706                                 }
9707 #if 0
9708                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9709 #endif
9710                                 k++;
9711                                 continue;
9712                         }
9713
9714                         status = cli_close(cli1, fnum1);
9715                         if (!NT_STATUS_IS_OK(status)) {
9716                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9717                                 return False;
9718                         }
9719
9720                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9721                         if (!NT_STATUS_IS_OK(status)) {
9722                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9723                                 return False;
9724                         }
9725
9726 #if 0
9727                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9728                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9729 #endif
9730
9731                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9732                                 if (attr_results[l].num == k) {
9733                                         if (attr != attr_results[l].result_attr ||
9734                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9735                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9736                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9737                                                 open_attrs_table[i],
9738                                                 open_attrs_table[j],
9739                                                 (unsigned int)attr,
9740                                                 attr_results[l].result_attr);
9741                                                 correct = False;
9742                                         }
9743                                         break;
9744                                 }
9745                         }
9746                         k++;
9747                 }
9748         }
9749
9750         cli_setatr(cli1, fname, 0, 0);
9751         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9752
9753         printf("open attr test %s.\n", correct ? "passed" : "failed");
9754
9755         if (!torture_close_connection(cli1)) {
9756                 correct = False;
9757         }
9758         return correct;
9759 }
9760
9761 static NTSTATUS list_fn(struct file_info *finfo,
9762                     const char *name, void *state)
9763 {
9764         int *matched = (int *)state;
9765         if (matched != NULL) {
9766                 *matched += 1;
9767         }
9768         return NT_STATUS_OK;
9769 }
9770
9771 /*
9772   test directory listing speed
9773  */
9774 static bool run_dirtest(int dummy)
9775 {
9776         int i;
9777         static struct cli_state *cli;
9778         uint16_t fnum;
9779         struct timeval core_start;
9780         bool correct = True;
9781         int matched;
9782
9783         printf("starting directory test\n");
9784
9785         if (!torture_open_connection(&cli, 0)) {
9786                 return False;
9787         }
9788
9789         smbXcli_conn_set_sockopt(cli->conn, sockops);
9790
9791         srandom(0);
9792         for (i=0;i<torture_numops;i++) {
9793                 fstring fname;
9794                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9795                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9796                         fprintf(stderr,"Failed to open %s\n", fname);
9797                         return False;
9798                 }
9799                 cli_close(cli, fnum);
9800         }
9801
9802         core_start = timeval_current();
9803
9804         matched = 0;
9805         cli_list(cli, "a*.*", 0, list_fn, &matched);
9806         printf("Matched %d\n", matched);
9807
9808         matched = 0;
9809         cli_list(cli, "b*.*", 0, list_fn, &matched);
9810         printf("Matched %d\n", matched);
9811
9812         matched = 0;
9813         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9814         printf("Matched %d\n", matched);
9815
9816         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9817
9818         srandom(0);
9819         for (i=0;i<torture_numops;i++) {
9820                 fstring fname;
9821                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9822                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9823         }
9824
9825         if (!torture_close_connection(cli)) {
9826                 correct = False;
9827         }
9828
9829         printf("finished dirtest\n");
9830
9831         return correct;
9832 }
9833
9834 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9835                    void *state)
9836 {
9837         struct cli_state *pcli = (struct cli_state *)state;
9838         fstring fname;
9839         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9840
9841         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9842                 return NT_STATUS_OK;
9843
9844         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9845                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9846                         printf("del_fn: failed to rmdir %s\n,", fname );
9847         } else {
9848                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9849                         printf("del_fn: failed to unlink %s\n,", fname );
9850         }
9851         return NT_STATUS_OK;
9852 }
9853
9854
9855 /*
9856   sees what IOCTLs are supported
9857  */
9858 bool torture_ioctl_test(int dummy)
9859 {
9860         static struct cli_state *cli;
9861         uint16_t device, function;
9862         uint16_t fnum;
9863         const char *fname = "\\ioctl.dat";
9864         DATA_BLOB blob;
9865         NTSTATUS status;
9866
9867         if (!torture_open_connection(&cli, 0)) {
9868                 return False;
9869         }
9870
9871         printf("starting ioctl test\n");
9872
9873         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9874
9875         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9876         if (!NT_STATUS_IS_OK(status)) {
9877                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9878                 return False;
9879         }
9880
9881         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9882         printf("ioctl device info: %s\n", nt_errstr(status));
9883
9884         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9885         printf("ioctl job info: %s\n", nt_errstr(status));
9886
9887         for (device=0;device<0x100;device++) {
9888                 printf("ioctl test with device = 0x%x\n", device);
9889                 for (function=0;function<0x100;function++) {
9890                         uint32_t code = (device<<16) | function;
9891
9892                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9893
9894                         if (NT_STATUS_IS_OK(status)) {
9895                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9896                                        (int)blob.length);
9897                                 data_blob_free(&blob);
9898                         }
9899                 }
9900         }
9901
9902         if (!torture_close_connection(cli)) {
9903                 return False;
9904         }
9905
9906         return True;
9907 }
9908
9909
9910 /*
9911   tries varients of chkpath
9912  */
9913 bool torture_chkpath_test(int dummy)
9914 {
9915         static struct cli_state *cli;
9916         uint16_t fnum;
9917         bool ret;
9918         NTSTATUS status;
9919
9920         if (!torture_open_connection(&cli, 0)) {
9921                 return False;
9922         }
9923
9924         printf("starting chkpath test\n");
9925
9926         /* cleanup from an old run */
9927         torture_deltree(cli, "\\chkpath.dir");
9928
9929         status = cli_mkdir(cli, "\\chkpath.dir");
9930         if (!NT_STATUS_IS_OK(status)) {
9931                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9932                 return False;
9933         }
9934
9935         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9936         if (!NT_STATUS_IS_OK(status)) {
9937                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9938                 return False;
9939         }
9940
9941         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9942                           DENY_NONE, &fnum);
9943         if (!NT_STATUS_IS_OK(status)) {
9944                 printf("open1 failed (%s)\n", nt_errstr(status));
9945                 return False;
9946         }
9947         cli_close(cli, fnum);
9948
9949         status = cli_chkpath(cli, "\\chkpath.dir");
9950         if (!NT_STATUS_IS_OK(status)) {
9951                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9952                 ret = False;
9953         }
9954
9955         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9956         if (!NT_STATUS_IS_OK(status)) {
9957                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9958                 ret = False;
9959         }
9960
9961         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9962         if (!NT_STATUS_IS_OK(status)) {
9963                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9964                                   NT_STATUS_NOT_A_DIRECTORY);
9965         } else {
9966                 printf("* chkpath on a file should fail\n");
9967                 ret = False;
9968         }
9969
9970         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9971         if (!NT_STATUS_IS_OK(status)) {
9972                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9973                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9974         } else {
9975                 printf("* chkpath on a non existent file should fail\n");
9976                 ret = False;
9977         }
9978
9979         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9980         if (!NT_STATUS_IS_OK(status)) {
9981                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9982                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9983         } else {
9984                 printf("* chkpath on a non existent component should fail\n");
9985                 ret = False;
9986         }
9987
9988         torture_deltree(cli, "\\chkpath.dir");
9989
9990         if (!torture_close_connection(cli)) {
9991                 return False;
9992         }
9993
9994         return ret;
9995 }
9996
9997 static bool run_eatest(int dummy)
9998 {
9999         static struct cli_state *cli;
10000         const char *fname = "\\eatest.txt";
10001         bool correct = True;
10002         uint16_t fnum;
10003         size_t i, num_eas;
10004         struct ea_struct *ea_list = NULL;
10005         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10006         NTSTATUS status;
10007
10008         printf("starting eatest\n");
10009
10010         if (!torture_open_connection(&cli, 0)) {
10011                 talloc_destroy(mem_ctx);
10012                 return False;
10013         }
10014
10015         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10016
10017         status = cli_ntcreate(cli, fname, 0,
10018                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10019                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10020                               0x4044, 0, &fnum, NULL);
10021         if (!NT_STATUS_IS_OK(status)) {
10022                 printf("open failed - %s\n", nt_errstr(status));
10023                 talloc_destroy(mem_ctx);
10024                 return False;
10025         }
10026
10027         for (i = 0; i < 10; i++) {
10028                 fstring ea_name, ea_val;
10029
10030                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10031                 memset(ea_val, (char)i+1, i+1);
10032                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10033                 if (!NT_STATUS_IS_OK(status)) {
10034                         printf("ea_set of name %s failed - %s\n", ea_name,
10035                                nt_errstr(status));
10036                         talloc_destroy(mem_ctx);
10037                         return False;
10038                 }
10039         }
10040
10041         cli_close(cli, fnum);
10042         for (i = 0; i < 10; i++) {
10043                 fstring ea_name, ea_val;
10044
10045                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10046                 memset(ea_val, (char)i+1, i+1);
10047                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10048                 if (!NT_STATUS_IS_OK(status)) {
10049                         printf("ea_set of name %s failed - %s\n", ea_name,
10050                                nt_errstr(status));
10051                         talloc_destroy(mem_ctx);
10052                         return False;
10053                 }
10054         }
10055
10056         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10057         if (!NT_STATUS_IS_OK(status)) {
10058                 printf("ea_get list failed - %s\n", nt_errstr(status));
10059                 correct = False;
10060         }
10061
10062         printf("num_eas = %d\n", (int)num_eas);
10063
10064         if (num_eas != 20) {
10065                 printf("Should be 20 EA's stored... failing.\n");
10066                 correct = False;
10067         }
10068
10069         for (i = 0; i < num_eas; i++) {
10070                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10071                 dump_data(0, ea_list[i].value.data,
10072                           ea_list[i].value.length);
10073         }
10074
10075         /* Setting EA's to zero length deletes them. Test this */
10076         printf("Now deleting all EA's - case indepenent....\n");
10077
10078 #if 1
10079         cli_set_ea_path(cli, fname, "", "", 0);
10080 #else
10081         for (i = 0; i < 20; i++) {
10082                 fstring ea_name;
10083                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10084                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10085                 if (!NT_STATUS_IS_OK(status)) {
10086                         printf("ea_set of name %s failed - %s\n", ea_name,
10087                                nt_errstr(status));
10088                         talloc_destroy(mem_ctx);
10089                         return False;
10090                 }
10091         }
10092 #endif
10093
10094         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10095         if (!NT_STATUS_IS_OK(status)) {
10096                 printf("ea_get list failed - %s\n", nt_errstr(status));
10097                 correct = False;
10098         }
10099
10100         printf("num_eas = %d\n", (int)num_eas);
10101         for (i = 0; i < num_eas; i++) {
10102                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10103                 dump_data(0, ea_list[i].value.data,
10104                           ea_list[i].value.length);
10105         }
10106
10107         if (num_eas != 0) {
10108                 printf("deleting EA's failed.\n");
10109                 correct = False;
10110         }
10111
10112         /* Try and delete a non existent EA. */
10113         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10114         if (!NT_STATUS_IS_OK(status)) {
10115                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10116                        nt_errstr(status));
10117                 correct = False;
10118         }
10119
10120         talloc_destroy(mem_ctx);
10121         if (!torture_close_connection(cli)) {
10122                 correct = False;
10123         }
10124
10125         return correct;
10126 }
10127
10128 static bool run_dirtest1(int dummy)
10129 {
10130         int i;
10131         static struct cli_state *cli;
10132         uint16_t fnum;
10133         int num_seen;
10134         bool correct = True;
10135
10136         printf("starting directory test\n");
10137
10138         if (!torture_open_connection(&cli, 0)) {
10139                 return False;
10140         }
10141
10142         smbXcli_conn_set_sockopt(cli->conn, sockops);
10143
10144         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10145         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10146         cli_rmdir(cli, "\\LISTDIR");
10147         cli_mkdir(cli, "\\LISTDIR");
10148
10149         /* Create 1000 files and 1000 directories. */
10150         for (i=0;i<1000;i++) {
10151                 fstring fname;
10152                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10153                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10154                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10155                                    0, 0, &fnum, NULL))) {
10156                         fprintf(stderr,"Failed to open %s\n", fname);
10157                         return False;
10158                 }
10159                 cli_close(cli, fnum);
10160         }
10161         for (i=0;i<1000;i++) {
10162                 fstring fname;
10163                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10164                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10165                         fprintf(stderr,"Failed to open %s\n", fname);
10166                         return False;
10167                 }
10168         }
10169
10170         /* Now ensure that doing an old list sees both files and directories. */
10171         num_seen = 0;
10172         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10173         printf("num_seen = %d\n", num_seen );
10174         /* We should see 100 files + 1000 directories + . and .. */
10175         if (num_seen != 2002)
10176                 correct = False;
10177
10178         /* Ensure if we have the "must have" bits we only see the
10179          * relevent entries.
10180          */
10181         num_seen = 0;
10182         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10183         printf("num_seen = %d\n", num_seen );
10184         if (num_seen != 1002)
10185                 correct = False;
10186
10187         num_seen = 0;
10188         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10189         printf("num_seen = %d\n", num_seen );
10190         if (num_seen != 1000)
10191                 correct = False;
10192
10193         /* Delete everything. */
10194         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10195         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10196         cli_rmdir(cli, "\\LISTDIR");
10197
10198 #if 0
10199         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10200         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10201         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10202 #endif
10203
10204         if (!torture_close_connection(cli)) {
10205                 correct = False;
10206         }
10207
10208         printf("finished dirtest1\n");
10209
10210         return correct;
10211 }
10212
10213 static bool run_error_map_extract(int dummy) {
10214
10215         static struct cli_state *c_dos;
10216         static struct cli_state *c_nt;
10217         NTSTATUS status;
10218
10219         uint32_t error;
10220
10221         uint32_t errnum;
10222         uint8_t errclass;
10223
10224         NTSTATUS nt_status;
10225
10226         fstring user;
10227
10228         /* NT-Error connection */
10229
10230         disable_spnego = true;
10231         if (!(c_nt = open_nbt_connection())) {
10232                 disable_spnego = false;
10233                 return False;
10234         }
10235         disable_spnego = false;
10236
10237         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10238                                  PROTOCOL_NT1);
10239
10240         if (!NT_STATUS_IS_OK(status)) {
10241                 printf("%s rejected the NT-error negprot (%s)\n", host,
10242                        nt_errstr(status));
10243                 cli_shutdown(c_nt);
10244                 return False;
10245         }
10246
10247         status = cli_session_setup_anon(c_nt);
10248         if (!NT_STATUS_IS_OK(status)) {
10249                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10250                 return False;
10251         }
10252
10253         /* DOS-Error connection */
10254
10255         disable_spnego = true;
10256         force_dos_errors = true;
10257         if (!(c_dos = open_nbt_connection())) {
10258                 disable_spnego = false;
10259                 force_dos_errors = false;
10260                 return False;
10261         }
10262         disable_spnego = false;
10263         force_dos_errors = false;
10264
10265         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10266                                  PROTOCOL_NT1);
10267         if (!NT_STATUS_IS_OK(status)) {
10268                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10269                        nt_errstr(status));
10270                 cli_shutdown(c_dos);
10271                 return False;
10272         }
10273
10274         status = cli_session_setup_anon(c_dos);
10275         if (!NT_STATUS_IS_OK(status)) {
10276                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10277                         host, nt_errstr(status));
10278                 return False;
10279         }
10280
10281         c_nt->map_dos_errors = false;
10282         c_dos->map_dos_errors = false;
10283
10284         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10285                 struct cli_credentials *user_creds = NULL;
10286
10287                 fstr_sprintf(user, "%X", error);
10288
10289                 user_creds = cli_session_creds_init(talloc_tos(),
10290                                                     user,
10291                                                     workgroup,
10292                                                     NULL, /* realm */
10293                                                     password,
10294                                                     false, /* use_kerberos */
10295                                                     false, /* fallback_after_kerberos */
10296                                                     false, /* use_ccache */
10297                                                     false); /* password_is_nt_hash */
10298                 if (user_creds == NULL) {
10299                         printf("cli_session_creds_init(%s) failed\n", user);
10300                         return false;
10301                 }
10302
10303                 status = cli_session_setup_creds(c_nt, user_creds);
10304                 if (NT_STATUS_IS_OK(status)) {
10305                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10306                 }
10307
10308                 /* Case #1: 32-bit NT errors */
10309                 if (!NT_STATUS_IS_DOS(status)) {
10310                         nt_status = status;
10311                 } else {
10312                         printf("/** Dos error on NT connection! (%s) */\n", 
10313                                nt_errstr(status));
10314                         nt_status = NT_STATUS(0xc0000000);
10315                 }
10316
10317                 status = cli_session_setup_creds(c_dos, user_creds);
10318                 if (NT_STATUS_IS_OK(status)) {
10319                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10320                 }
10321
10322                 /* Case #1: 32-bit NT errors */
10323                 if (NT_STATUS_IS_DOS(status)) {
10324                         printf("/** NT error on DOS connection! (%s) */\n", 
10325                                nt_errstr(status));
10326                         errnum = errclass = 0;
10327                 } else {
10328                         errclass = NT_STATUS_DOS_CLASS(status);
10329                         errnum = NT_STATUS_DOS_CODE(status);
10330                 }
10331
10332                 if (NT_STATUS_V(nt_status) != error) { 
10333                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10334                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10335                                get_nt_error_c_code(talloc_tos(), nt_status));
10336                 }
10337
10338                 printf("\t{%s,\t%s,\t%s},\n", 
10339                        smb_dos_err_class(errclass), 
10340                        smb_dos_err_name(errclass, errnum), 
10341                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10342
10343                 TALLOC_FREE(user_creds);
10344         }
10345         return True;
10346 }
10347
10348 static bool run_sesssetup_bench(int dummy)
10349 {
10350         static struct cli_state *c;
10351         const char *fname = "\\file.dat";
10352         uint16_t fnum;
10353         NTSTATUS status;
10354         int i;
10355
10356         if (!torture_open_connection(&c, 0)) {
10357                 return false;
10358         }
10359
10360         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10361                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10362                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10363         if (!NT_STATUS_IS_OK(status)) {
10364                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10365                 return false;
10366         }
10367
10368         for (i=0; i<torture_numops; i++) {
10369                 status = cli_session_setup_creds(c, torture_creds);
10370                 if (!NT_STATUS_IS_OK(status)) {
10371                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10372                                  __location__, nt_errstr(status));
10373                         return false;
10374                 }
10375
10376                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10377
10378                 status = cli_ulogoff(c);
10379                 if (!NT_STATUS_IS_OK(status)) {
10380                         d_printf("(%s) cli_ulogoff failed: %s\n",
10381                                  __location__, nt_errstr(status));
10382                         return false;
10383                 }
10384         }
10385
10386         return true;
10387 }
10388
10389 static bool subst_test(const char *str, const char *user, const char *domain,
10390                        uid_t uid, gid_t gid, const char *expected)
10391 {
10392         char *subst;
10393         bool result = true;
10394
10395         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10396
10397         if (strcmp(subst, expected) != 0) {
10398                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10399                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10400                        expected);
10401                 result = false;
10402         }
10403
10404         TALLOC_FREE(subst);
10405         return result;
10406 }
10407
10408 static void chain1_open_completion(struct tevent_req *req)
10409 {
10410         uint16_t fnum;
10411         NTSTATUS status;
10412         status = cli_openx_recv(req, &fnum);
10413         TALLOC_FREE(req);
10414
10415         d_printf("cli_openx_recv returned %s: %d\n",
10416                  nt_errstr(status),
10417                  NT_STATUS_IS_OK(status) ? fnum : -1);
10418 }
10419
10420 static void chain1_write_completion(struct tevent_req *req)
10421 {
10422         size_t written;
10423         NTSTATUS status;
10424         status = cli_write_andx_recv(req, &written);
10425         TALLOC_FREE(req);
10426
10427         d_printf("cli_write_andx_recv returned %s: %d\n",
10428                  nt_errstr(status),
10429                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10430 }
10431
10432 static void chain1_close_completion(struct tevent_req *req)
10433 {
10434         NTSTATUS status;
10435         bool *done = (bool *)tevent_req_callback_data_void(req);
10436
10437         status = cli_close_recv(req);
10438         *done = true;
10439
10440         TALLOC_FREE(req);
10441
10442         d_printf("cli_close returned %s\n", nt_errstr(status));
10443 }
10444
10445 static bool run_chain1(int dummy)
10446 {
10447         struct cli_state *cli1;
10448         struct tevent_context *evt = samba_tevent_context_init(NULL);
10449         struct tevent_req *reqs[3], *smbreqs[3];
10450         bool done = false;
10451         const char *str = "foobar";
10452         const char *fname = "\\test_chain";
10453         NTSTATUS status;
10454
10455         printf("starting chain1 test\n");
10456         if (!torture_open_connection(&cli1, 0)) {
10457                 return False;
10458         }
10459
10460         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10461
10462         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10463
10464         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10465                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10466         if (reqs[0] == NULL) return false;
10467         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10468
10469
10470         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10471                                         (const uint8_t *)str, 0, strlen(str)+1,
10472                                         smbreqs, 1, &smbreqs[1]);
10473         if (reqs[1] == NULL) return false;
10474         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10475
10476         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10477         if (reqs[2] == NULL) return false;
10478         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10479
10480         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10481         if (!NT_STATUS_IS_OK(status)) {
10482                 return false;
10483         }
10484
10485         while (!done) {
10486                 tevent_loop_once(evt);
10487         }
10488
10489         torture_close_connection(cli1);
10490         return True;
10491 }
10492
10493 static void chain2_sesssetup_completion(struct tevent_req *req)
10494 {
10495         NTSTATUS status;
10496         status = cli_session_setup_guest_recv(req);
10497         d_printf("sesssetup returned %s\n", nt_errstr(status));
10498 }
10499
10500 static void chain2_tcon_completion(struct tevent_req *req)
10501 {
10502         bool *done = (bool *)tevent_req_callback_data_void(req);
10503         NTSTATUS status;
10504         status = cli_tcon_andx_recv(req);
10505         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10506         *done = true;
10507 }
10508
10509 static bool run_chain2(int dummy)
10510 {
10511         struct cli_state *cli1;
10512         struct tevent_context *evt = samba_tevent_context_init(NULL);
10513         struct tevent_req *reqs[2], *smbreqs[2];
10514         bool done = false;
10515         NTSTATUS status;
10516         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10517
10518         printf("starting chain2 test\n");
10519         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10520                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10521         if (!NT_STATUS_IS_OK(status)) {
10522                 return False;
10523         }
10524
10525         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10526
10527         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10528                                                  &smbreqs[0]);
10529         if (reqs[0] == NULL) return false;
10530         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10531
10532         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10533                                        "?????", NULL, 0, &smbreqs[1]);
10534         if (reqs[1] == NULL) return false;
10535         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10536
10537         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10538         if (!NT_STATUS_IS_OK(status)) {
10539                 return false;
10540         }
10541
10542         while (!done) {
10543                 tevent_loop_once(evt);
10544         }
10545
10546         torture_close_connection(cli1);
10547         return True;
10548 }
10549
10550
10551 struct torture_createdel_state {
10552         struct tevent_context *ev;
10553         struct cli_state *cli;
10554 };
10555
10556 static void torture_createdel_created(struct tevent_req *subreq);
10557 static void torture_createdel_closed(struct tevent_req *subreq);
10558
10559 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10560                                                  struct tevent_context *ev,
10561                                                  struct cli_state *cli,
10562                                                  const char *name)
10563 {
10564         struct tevent_req *req, *subreq;
10565         struct torture_createdel_state *state;
10566
10567         req = tevent_req_create(mem_ctx, &state,
10568                                 struct torture_createdel_state);
10569         if (req == NULL) {
10570                 return NULL;
10571         }
10572         state->ev = ev;
10573         state->cli = cli;
10574
10575         subreq = cli_ntcreate_send(
10576                 state, ev, cli, name, 0,
10577                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10578                 FILE_ATTRIBUTE_NORMAL,
10579                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10580                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10581                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10582
10583         if (tevent_req_nomem(subreq, req)) {
10584                 return tevent_req_post(req, ev);
10585         }
10586         tevent_req_set_callback(subreq, torture_createdel_created, req);
10587         return req;
10588 }
10589
10590 static void torture_createdel_created(struct tevent_req *subreq)
10591 {
10592         struct tevent_req *req = tevent_req_callback_data(
10593                 subreq, struct tevent_req);
10594         struct torture_createdel_state *state = tevent_req_data(
10595                 req, struct torture_createdel_state);
10596         NTSTATUS status;
10597         uint16_t fnum;
10598
10599         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10600         TALLOC_FREE(subreq);
10601         if (tevent_req_nterror(req, status)) {
10602                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10603                            nt_errstr(status)));
10604                 return;
10605         }
10606
10607         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10608         if (tevent_req_nomem(subreq, req)) {
10609                 return;
10610         }
10611         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10612 }
10613
10614 static void torture_createdel_closed(struct tevent_req *subreq)
10615 {
10616         struct tevent_req *req = tevent_req_callback_data(
10617                 subreq, struct tevent_req);
10618         NTSTATUS status;
10619
10620         status = cli_close_recv(subreq);
10621         if (tevent_req_nterror(req, status)) {
10622                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10623                 return;
10624         }
10625         tevent_req_done(req);
10626 }
10627
10628 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10629 {
10630         return tevent_req_simple_recv_ntstatus(req);
10631 }
10632
10633 struct torture_createdels_state {
10634         struct tevent_context *ev;
10635         struct cli_state *cli;
10636         const char *base_name;
10637         int sent;
10638         int received;
10639         int num_files;
10640         struct tevent_req **reqs;
10641 };
10642
10643 static void torture_createdels_done(struct tevent_req *subreq);
10644
10645 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10646                                                   struct tevent_context *ev,
10647                                                   struct cli_state *cli,
10648                                                   const char *base_name,
10649                                                   int num_parallel,
10650                                                   int num_files)
10651 {
10652         struct tevent_req *req;
10653         struct torture_createdels_state *state;
10654         int i;
10655
10656         req = tevent_req_create(mem_ctx, &state,
10657                                 struct torture_createdels_state);
10658         if (req == NULL) {
10659                 return NULL;
10660         }
10661         state->ev = ev;
10662         state->cli = cli;
10663         state->base_name = talloc_strdup(state, base_name);
10664         if (tevent_req_nomem(state->base_name, req)) {
10665                 return tevent_req_post(req, ev);
10666         }
10667         state->num_files = MAX(num_parallel, num_files);
10668         state->sent = 0;
10669         state->received = 0;
10670
10671         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10672         if (tevent_req_nomem(state->reqs, req)) {
10673                 return tevent_req_post(req, ev);
10674         }
10675
10676         for (i=0; i<num_parallel; i++) {
10677                 char *name;
10678
10679                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10680                                        state->sent);
10681                 if (tevent_req_nomem(name, req)) {
10682                         return tevent_req_post(req, ev);
10683                 }
10684                 state->reqs[i] = torture_createdel_send(
10685                         state->reqs, state->ev, state->cli, name);
10686                 if (tevent_req_nomem(state->reqs[i], req)) {
10687                         return tevent_req_post(req, ev);
10688                 }
10689                 name = talloc_move(state->reqs[i], &name);
10690                 tevent_req_set_callback(state->reqs[i],
10691                                         torture_createdels_done, req);
10692                 state->sent += 1;
10693         }
10694         return req;
10695 }
10696
10697 static void torture_createdels_done(struct tevent_req *subreq)
10698 {
10699         struct tevent_req *req = tevent_req_callback_data(
10700                 subreq, struct tevent_req);
10701         struct torture_createdels_state *state = tevent_req_data(
10702                 req, struct torture_createdels_state);
10703         size_t i, num_parallel = talloc_array_length(state->reqs);
10704         NTSTATUS status;
10705         char *name;
10706
10707         status = torture_createdel_recv(subreq);
10708         if (!NT_STATUS_IS_OK(status)){
10709                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10710                            nt_errstr(status)));
10711                 TALLOC_FREE(subreq);
10712                 tevent_req_nterror(req, status);
10713                 return;
10714         }
10715
10716         for (i=0; i<num_parallel; i++) {
10717                 if (subreq == state->reqs[i]) {
10718                         break;
10719                 }
10720         }
10721         if (i == num_parallel) {
10722                 DEBUG(10, ("received something we did not send\n"));
10723                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10724                 return;
10725         }
10726         TALLOC_FREE(state->reqs[i]);
10727
10728         if (state->sent >= state->num_files) {
10729                 tevent_req_done(req);
10730                 return;
10731         }
10732
10733         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10734                                state->sent);
10735         if (tevent_req_nomem(name, req)) {
10736                 return;
10737         }
10738         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10739                                                 state->cli, name);
10740         if (tevent_req_nomem(state->reqs[i], req)) {
10741                 return;
10742         }
10743         name = talloc_move(state->reqs[i], &name);
10744         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10745         state->sent += 1;
10746 }
10747
10748 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10749 {
10750         return tevent_req_simple_recv_ntstatus(req);
10751 }
10752
10753 struct swallow_notify_state {
10754         struct tevent_context *ev;
10755         struct cli_state *cli;
10756         uint16_t fnum;
10757         uint32_t completion_filter;
10758         bool recursive;
10759         bool (*fn)(uint32_t action, const char *name, void *priv);
10760         void *priv;
10761 };
10762
10763 static void swallow_notify_done(struct tevent_req *subreq);
10764
10765 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10766                                               struct tevent_context *ev,
10767                                               struct cli_state *cli,
10768                                               uint16_t fnum,
10769                                               uint32_t completion_filter,
10770                                               bool recursive,
10771                                               bool (*fn)(uint32_t action,
10772                                                          const char *name,
10773                                                          void *priv),
10774                                               void *priv)
10775 {
10776         struct tevent_req *req, *subreq;
10777         struct swallow_notify_state *state;
10778
10779         req = tevent_req_create(mem_ctx, &state,
10780                                 struct swallow_notify_state);
10781         if (req == NULL) {
10782                 return NULL;
10783         }
10784         state->ev = ev;
10785         state->cli = cli;
10786         state->fnum = fnum;
10787         state->completion_filter = completion_filter;
10788         state->recursive = recursive;
10789         state->fn = fn;
10790         state->priv = priv;
10791
10792         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10793                                  0xffff, state->completion_filter,
10794                                  state->recursive);
10795         if (tevent_req_nomem(subreq, req)) {
10796                 return tevent_req_post(req, ev);
10797         }
10798         tevent_req_set_callback(subreq, swallow_notify_done, req);
10799         return req;
10800 }
10801
10802 static void swallow_notify_done(struct tevent_req *subreq)
10803 {
10804         struct tevent_req *req = tevent_req_callback_data(
10805                 subreq, struct tevent_req);
10806         struct swallow_notify_state *state = tevent_req_data(
10807                 req, struct swallow_notify_state);
10808         NTSTATUS status;
10809         uint32_t i, num_changes;
10810         struct notify_change *changes;
10811
10812         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10813         TALLOC_FREE(subreq);
10814         if (!NT_STATUS_IS_OK(status)) {
10815                 DEBUG(10, ("cli_notify_recv returned %s\n",
10816                            nt_errstr(status)));
10817                 tevent_req_nterror(req, status);
10818                 return;
10819         }
10820
10821         for (i=0; i<num_changes; i++) {
10822                 state->fn(changes[i].action, changes[i].name, state->priv);
10823         }
10824         TALLOC_FREE(changes);
10825
10826         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10827                                  0xffff, state->completion_filter,
10828                                  state->recursive);
10829         if (tevent_req_nomem(subreq, req)) {
10830                 return;
10831         }
10832         tevent_req_set_callback(subreq, swallow_notify_done, req);
10833 }
10834
10835 static bool print_notifies(uint32_t action, const char *name, void *priv)
10836 {
10837         if (DEBUGLEVEL > 5) {
10838                 d_printf("%d %s\n", (int)action, name);
10839         }
10840         return true;
10841 }
10842
10843 static void notify_bench_done(struct tevent_req *req)
10844 {
10845         int *num_finished = (int *)tevent_req_callback_data_void(req);
10846         *num_finished += 1;
10847 }
10848
10849 static bool run_notify_bench(int dummy)
10850 {
10851         const char *dname = "\\notify-bench";
10852         struct tevent_context *ev;
10853         NTSTATUS status;
10854         uint16_t dnum;
10855         struct tevent_req *req1;
10856         struct tevent_req *req2 = NULL;
10857         int i, num_unc_names;
10858         int num_finished = 0;
10859
10860         printf("starting notify-bench test\n");
10861
10862         if (use_multishare_conn) {
10863                 char **unc_list;
10864                 unc_list = file_lines_load(multishare_conn_fname,
10865                                            &num_unc_names, 0, NULL);
10866                 if (!unc_list || num_unc_names <= 0) {
10867                         d_printf("Failed to load unc names list from '%s'\n",
10868                                  multishare_conn_fname);
10869                         return false;
10870                 }
10871                 TALLOC_FREE(unc_list);
10872         } else {
10873                 num_unc_names = 1;
10874         }
10875
10876         ev = samba_tevent_context_init(talloc_tos());
10877         if (ev == NULL) {
10878                 d_printf("tevent_context_init failed\n");
10879                 return false;
10880         }
10881
10882         for (i=0; i<num_unc_names; i++) {
10883                 struct cli_state *cli;
10884                 char *base_fname;
10885
10886                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10887                                              dname, i);
10888                 if (base_fname == NULL) {
10889                         return false;
10890                 }
10891
10892                 if (!torture_open_connection(&cli, i)) {
10893                         return false;
10894                 }
10895
10896                 status = cli_ntcreate(cli, dname, 0,
10897                                       MAXIMUM_ALLOWED_ACCESS,
10898                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10899                                       FILE_SHARE_DELETE,
10900                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10901                                       &dnum, NULL);
10902
10903                 if (!NT_STATUS_IS_OK(status)) {
10904                         d_printf("Could not create %s: %s\n", dname,
10905                                  nt_errstr(status));
10906                         return false;
10907                 }
10908
10909                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10910                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10911                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10912                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10913                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10914                                            false, print_notifies, NULL);
10915                 if (req1 == NULL) {
10916                         d_printf("Could not create notify request\n");
10917                         return false;
10918                 }
10919
10920                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10921                                                base_fname, 10, torture_numops);
10922                 if (req2 == NULL) {
10923                         d_printf("Could not create createdels request\n");
10924                         return false;
10925                 }
10926                 TALLOC_FREE(base_fname);
10927
10928                 tevent_req_set_callback(req2, notify_bench_done,
10929                                         &num_finished);
10930         }
10931
10932         while (num_finished < num_unc_names) {
10933                 int ret;
10934                 ret = tevent_loop_once(ev);
10935                 if (ret != 0) {
10936                         d_printf("tevent_loop_once failed\n");
10937                         return false;
10938                 }
10939         }
10940
10941         if (!tevent_req_poll(req2, ev)) {
10942                 d_printf("tevent_req_poll failed\n");
10943         }
10944
10945         status = torture_createdels_recv(req2);
10946         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10947
10948         return true;
10949 }
10950
10951 static bool run_mangle1(int dummy)
10952 {
10953         struct cli_state *cli;
10954         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10955         uint16_t fnum;
10956         fstring alt_name;
10957         NTSTATUS status;
10958         time_t change_time, access_time, write_time;
10959         off_t size;
10960         uint32_t attr;
10961
10962         printf("starting mangle1 test\n");
10963         if (!torture_open_connection(&cli, 0)) {
10964                 return False;
10965         }
10966
10967         smbXcli_conn_set_sockopt(cli->conn, sockops);
10968
10969         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10970                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10971                               0, 0, &fnum, NULL);
10972         if (!NT_STATUS_IS_OK(status)) {
10973                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10974                 return false;
10975         }
10976         cli_close(cli, fnum);
10977
10978         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10979         if (!NT_STATUS_IS_OK(status)) {
10980                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10981                          nt_errstr(status));
10982                 return false;
10983         }
10984         d_printf("alt_name: %s\n", alt_name);
10985
10986         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10987         if (!NT_STATUS_IS_OK(status)) {
10988                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10989                          nt_errstr(status));
10990                 return false;
10991         }
10992         cli_close(cli, fnum);
10993
10994         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10995                                 &write_time, &size, &attr);
10996         if (!NT_STATUS_IS_OK(status)) {
10997                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10998                          nt_errstr(status));
10999                 return false;
11000         }
11001
11002         return true;
11003 }
11004
11005 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11006                                                  const char *mask,
11007                                                  void *state)
11008 {
11009         if (f->short_name == NULL) {
11010                 return NT_STATUS_OK;
11011         }
11012
11013         if (strlen(f->short_name) == 0) {
11014                 return NT_STATUS_OK;
11015         }
11016
11017         printf("unexpected shortname: %s\n", f->short_name);
11018
11019         return NT_STATUS_OBJECT_NAME_INVALID;
11020 }
11021
11022 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11023                                             const char *mask,
11024                                             void *state)
11025 {
11026         char *name = state;
11027
11028         printf("name: %s\n", f->name);
11029         fstrcpy(name, f->name);
11030         return NT_STATUS_OK;
11031 }
11032
11033 static bool run_mangle_illegal(int dummy)
11034 {
11035         struct cli_state *cli = NULL;
11036         struct cli_state *cli_posix = NULL;
11037         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11038         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11039         char *mangled_path = NULL;
11040         uint16_t fnum;
11041         fstring name;
11042         fstring alt_name;
11043         NTSTATUS status;
11044
11045         printf("starting mangle-illegal test\n");
11046
11047         if (!torture_open_connection(&cli, 0)) {
11048                 return False;
11049         }
11050
11051         smbXcli_conn_set_sockopt(cli->conn, sockops);
11052
11053         if (!torture_open_connection(&cli_posix, 0)) {
11054                 return false;
11055         }
11056
11057         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11058
11059         status = torture_setup_unix_extensions(cli_posix);
11060         if (!NT_STATUS_IS_OK(status)) {
11061                 return false;
11062         }
11063
11064         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11065         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11066         if (!NT_STATUS_IS_OK(status)) {
11067                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11068                 return False;
11069         }
11070
11071         /*
11072          * Create a file with illegal NTFS characters and test that we
11073          * get a usable mangled name
11074          */
11075
11076         cli_setatr(cli_posix, illegal_fname, 0, 0);
11077         cli_posix_unlink(cli_posix, illegal_fname);
11078
11079         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11080                                 0600, &fnum);
11081         if (!NT_STATUS_IS_OK(status)) {
11082                 printf("POSIX create of %s failed (%s)\n",
11083                        illegal_fname, nt_errstr(status));
11084                 return false;
11085         }
11086
11087         status = cli_close(cli_posix, fnum);
11088         if (!NT_STATUS_IS_OK(status)) {
11089                 printf("close failed (%s)\n", nt_errstr(status));
11090                 return false;
11091         }
11092
11093         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11094         if (!NT_STATUS_IS_OK(status)) {
11095                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11096                 return false;
11097         }
11098
11099         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11100         if (mangled_path == NULL) {
11101                 return false;
11102         }
11103
11104         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11105         if (!NT_STATUS_IS_OK(status)) {
11106                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11107                 TALLOC_FREE(mangled_path);
11108                 return false;
11109         }
11110         TALLOC_FREE(mangled_path);
11111         cli_close(cli, fnum);
11112
11113         cli_setatr(cli_posix, illegal_fname, 0, 0);
11114         cli_posix_unlink(cli_posix, illegal_fname);
11115
11116         /*
11117          * Create a file with a long name and check that we got *no* short name.
11118          */
11119
11120         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11121                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11122                               0, 0, &fnum, NULL);
11123         if (!NT_STATUS_IS_OK(status)) {
11124                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11125                 return false;
11126         }
11127         cli_close(cli, fnum);
11128
11129         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11130         if (!NT_STATUS_IS_OK(status)) {
11131                 d_printf("cli_list failed\n");
11132                 return false;
11133         }
11134
11135         cli_unlink(cli, fname, 0);
11136         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11137
11138         if (!torture_close_connection(cli_posix)) {
11139                 return false;
11140         }
11141
11142         if (!torture_close_connection(cli)) {
11143                 return false;
11144         }
11145
11146         return true;
11147 }
11148
11149 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11150 {
11151         size_t *to_pull = (size_t *)priv;
11152         size_t thistime = *to_pull;
11153
11154         thistime = MIN(thistime, n);
11155         if (thistime == 0) {
11156                 return 0;
11157         }
11158
11159         memset(buf, 0, thistime);
11160         *to_pull -= thistime;
11161         return thistime;
11162 }
11163
11164 static bool run_windows_write(int dummy)
11165 {
11166         struct cli_state *cli1;
11167         uint16_t fnum;
11168         int i;
11169         bool ret = false;
11170         const char *fname = "\\writetest.txt";
11171         struct timeval start_time;
11172         double seconds;
11173         double kbytes;
11174         NTSTATUS status;
11175
11176         printf("starting windows_write test\n");
11177         if (!torture_open_connection(&cli1, 0)) {
11178                 return False;
11179         }
11180
11181         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11182         if (!NT_STATUS_IS_OK(status)) {
11183                 printf("open failed (%s)\n", nt_errstr(status));
11184                 return False;
11185         }
11186
11187         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11188
11189         start_time = timeval_current();
11190
11191         for (i=0; i<torture_numops; i++) {
11192                 uint8_t c = 0;
11193                 off_t start = i * torture_blocksize;
11194                 size_t to_pull = torture_blocksize - 1;
11195
11196                 status = cli_writeall(cli1, fnum, 0, &c,
11197                                       start + torture_blocksize - 1, 1, NULL);
11198                 if (!NT_STATUS_IS_OK(status)) {
11199                         printf("cli_write failed: %s\n", nt_errstr(status));
11200                         goto fail;
11201                 }
11202
11203                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11204                                   null_source, &to_pull);
11205                 if (!NT_STATUS_IS_OK(status)) {
11206                         printf("cli_push returned: %s\n", nt_errstr(status));
11207                         goto fail;
11208                 }
11209         }
11210
11211         seconds = timeval_elapsed(&start_time);
11212         kbytes = (double)torture_blocksize * torture_numops;
11213         kbytes /= 1024;
11214
11215         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11216                (double)seconds, (int)(kbytes/seconds));
11217
11218         ret = true;
11219  fail:
11220         cli_close(cli1, fnum);
11221         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11222         torture_close_connection(cli1);
11223         return ret;
11224 }
11225
11226 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11227 {
11228         size_t max_pdu = 0x1FFFF;
11229
11230         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11231                 max_pdu = 0xFFFFFF;
11232         }
11233
11234         if (smb1cli_conn_signing_is_active(cli->conn)) {
11235                 max_pdu = 0x1FFFF;
11236         }
11237
11238         if (smb1cli_conn_encryption_on(cli->conn)) {
11239                 max_pdu = CLI_BUFFER_SIZE;
11240         }
11241
11242         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11243                 len_requested &= 0xFFFF;
11244         }
11245
11246         return MIN(len_requested,
11247                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11248 }
11249
11250 static bool check_read_call(struct cli_state *cli,
11251                             uint16_t fnum,
11252                             uint8_t *buf,
11253                             size_t len_requested)
11254 {
11255         NTSTATUS status;
11256         struct tevent_req *subreq = NULL;
11257         ssize_t len_read = 0;
11258         size_t len_expected = 0;
11259         struct tevent_context *ev = NULL;
11260
11261         ev = samba_tevent_context_init(talloc_tos());
11262         if (ev == NULL) {
11263                 return false;
11264         }
11265
11266         subreq = cli_read_andx_send(talloc_tos(),
11267                                     ev,
11268                                     cli,
11269                                     fnum,
11270                                     0,
11271                                     len_requested);
11272
11273         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11274                 return false;
11275         }
11276
11277         status = cli_read_andx_recv(subreq, &len_read, &buf);
11278         if (!NT_STATUS_IS_OK(status)) {
11279                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11280                 return false;
11281         }
11282
11283         TALLOC_FREE(subreq);
11284         TALLOC_FREE(ev);
11285
11286         len_expected = calc_expected_return(cli, len_requested);
11287
11288         if (len_expected > 0x10000 && len_read == 0x10000) {
11289                 /* Windows servers only return a max of 0x10000,
11290                    doesn't matter if you set CAP_LARGE_READX in
11291                    the client sessionsetupX call or not. */
11292                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11293                         (unsigned int)len_requested);
11294         } else if (len_read != len_expected) {
11295                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11296                         (unsigned int)len_requested,
11297                         (unsigned int)len_read,
11298                         (unsigned int)len_expected);
11299                 return false;
11300         } else {
11301                 d_printf("Correct read reply.\n");
11302         }
11303
11304         return true;
11305 }
11306
11307 /* Test large readX variants. */
11308 static bool large_readx_tests(struct cli_state *cli,
11309                                 uint16_t fnum,
11310                                 uint8_t *buf)
11311 {
11312         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11313         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11314                 return false;
11315         }
11316         /* A read of 0x10000 should return 0x10000 bytes. */
11317         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11318                 return false;
11319         }
11320         /* A read of 0x10000 should return 0x10001 bytes. */
11321         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11322                 return false;
11323         }
11324         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11325            the requested number of bytes. */
11326         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11327                 return false;
11328         }
11329         /* A read of 1MB should return 1MB bytes (on Samba). */
11330         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11331                 return false;
11332         }
11333
11334         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11335                 return false;
11336         }
11337         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11338                 return false;
11339         }
11340         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11341                 return false;
11342         }
11343         return true;
11344 }
11345
11346 static bool run_large_readx(int dummy)
11347 {
11348         uint8_t *buf = NULL;
11349         struct cli_state *cli1 = NULL;
11350         struct cli_state *cli2 = NULL;
11351         bool correct = false;
11352         const char *fname = "\\large_readx.dat";
11353         NTSTATUS status;
11354         uint16_t fnum1 = UINT16_MAX;
11355         uint32_t normal_caps = 0;
11356         size_t file_size = 20*1024*1024;
11357         TALLOC_CTX *frame = talloc_stackframe();
11358         size_t i;
11359         struct {
11360                 const char *name;
11361                 enum smb_signing_setting signing_setting;
11362                 enum protocol_types protocol;
11363         } runs[] = {
11364                 {
11365                         .name = "NT1",
11366                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11367                         .protocol = PROTOCOL_NT1,
11368                 },{
11369                         .name = "NT1 - SIGNING_REQUIRED",
11370                         .signing_setting = SMB_SIGNING_REQUIRED,
11371                         .protocol = PROTOCOL_NT1,
11372                 },
11373         };
11374
11375         printf("starting large_readx test\n");
11376
11377         if (!torture_open_connection(&cli1, 0)) {
11378                 goto out;
11379         }
11380
11381         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11382
11383         if (!(normal_caps & CAP_LARGE_READX)) {
11384                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11385                         (unsigned int)normal_caps);
11386                 goto out;
11387         }
11388
11389         /* Create a file of size 4MB. */
11390         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11391                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11392                         0, 0, &fnum1, NULL);
11393
11394         if (!NT_STATUS_IS_OK(status)) {
11395                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11396                 goto out;
11397         }
11398
11399         /* Write file_size bytes. */
11400         buf = talloc_zero_array(frame, uint8_t, file_size);
11401         if (buf == NULL) {
11402                 goto out;
11403         }
11404
11405         status = cli_writeall(cli1,
11406                               fnum1,
11407                               0,
11408                               buf,
11409                               0,
11410                               file_size,
11411                               NULL);
11412         if (!NT_STATUS_IS_OK(status)) {
11413                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11414                 goto out;
11415         }
11416
11417         status = cli_close(cli1, fnum1);
11418         if (!NT_STATUS_IS_OK(status)) {
11419                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11420                 goto out;
11421         }
11422
11423         fnum1 = UINT16_MAX;
11424
11425         for (i=0; i < ARRAY_SIZE(runs); i++) {
11426                 enum smb_signing_setting saved_signing_setting = signing_state;
11427                 uint16_t fnum2 = -1;
11428
11429                 if (do_encrypt &&
11430                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11431                 {
11432                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11433                         continue;
11434                 }
11435
11436                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11437
11438                 signing_state = runs[i].signing_setting;
11439                 cli2 = open_nbt_connection();
11440                 signing_state = saved_signing_setting;
11441                 if (cli2 == NULL) {
11442                         goto out;
11443                 }
11444
11445                 status = smbXcli_negprot(cli2->conn,
11446                                          cli2->timeout,
11447                                          runs[i].protocol,
11448                                          runs[i].protocol);
11449                 if (!NT_STATUS_IS_OK(status)) {
11450                         goto out;
11451                 }
11452
11453                 status = cli_session_setup_creds(cli2, torture_creds);
11454                 if (!NT_STATUS_IS_OK(status)) {
11455                         goto out;
11456                 }
11457
11458                 status = cli_tree_connect(cli2,
11459                                         share,
11460                                         "?????",
11461                                         password);
11462                 if (!NT_STATUS_IS_OK(status)) {
11463                         goto out;
11464                 }
11465
11466                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11467
11468                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11469
11470                 if (!(normal_caps & CAP_LARGE_READX)) {
11471                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11472                                 (unsigned int)normal_caps);
11473                         goto out;
11474                 }
11475
11476                 if (do_encrypt) {
11477                         if (force_cli_encryption(cli2, share) == false) {
11478                                 goto out;
11479                         }
11480                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11481                         uint16_t major, minor;
11482                         uint32_t caplow, caphigh;
11483
11484                         status = cli_unix_extensions_version(cli2,
11485                                                              &major, &minor,
11486                                                              &caplow, &caphigh);
11487                         if (!NT_STATUS_IS_OK(status)) {
11488                                 goto out;
11489                         }
11490                 }
11491
11492                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11493                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11494                                 0, 0, &fnum2, NULL);
11495                 if (!NT_STATUS_IS_OK(status)) {
11496                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11497                         goto out;
11498                 }
11499
11500                 /* All reads must return less than file_size bytes. */
11501                 if (!large_readx_tests(cli2, fnum2, buf)) {
11502                         goto out;
11503                 }
11504
11505                 status = cli_close(cli2, fnum2);
11506                 if (!NT_STATUS_IS_OK(status)) {
11507                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11508                         goto out;
11509                 }
11510                 fnum2 = -1;
11511
11512                 if (!torture_close_connection(cli2)) {
11513                         goto out;
11514                 }
11515                 cli2 = NULL;
11516         }
11517
11518         correct = true;
11519         printf("Success on large_readx test\n");
11520
11521   out:
11522
11523         if (cli2) {
11524                 if (!torture_close_connection(cli2)) {
11525                         correct = false;
11526                 }
11527         }
11528
11529         if (cli1) {
11530                 if (fnum1 != UINT16_MAX) {
11531                         status = cli_close(cli1, fnum1);
11532                         if (!NT_STATUS_IS_OK(status)) {
11533                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11534                         }
11535                         fnum1 = UINT16_MAX;
11536                 }
11537
11538                 status = cli_unlink(cli1, fname,
11539                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11540                 if (!NT_STATUS_IS_OK(status)) {
11541                         printf("unlink failed (%s)\n", nt_errstr(status));
11542                 }
11543
11544                 if (!torture_close_connection(cli1)) {
11545                         correct = false;
11546                 }
11547         }
11548
11549         TALLOC_FREE(frame);
11550
11551         printf("finished large_readx test\n");
11552         return correct;
11553 }
11554
11555 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11556                                   const char *mask,
11557                                   void *private_data)
11558 {
11559         uint32_t *p_attr = (uint32_t *)private_data;
11560
11561         if (strequal(finfo->name, test_filename)) {
11562                 *p_attr = finfo->attr;
11563         }
11564
11565         return NT_STATUS_OK;
11566 }
11567
11568 static bool run_msdfs_attribute(int dummy)
11569 {
11570         static struct cli_state *cli;
11571         bool correct = false;
11572         uint32_t attr = 0;
11573         NTSTATUS status;
11574
11575         printf("Starting MSDFS-ATTRIBUTE test\n");
11576
11577         if (test_filename == NULL || test_filename[0] == '\0') {
11578                 printf("MSDFS-ATTRIBUTE test "
11579                         "needs -f filename-of-msdfs-link\n");
11580                 return false;
11581         }
11582
11583         /*
11584          * NB. We use torture_open_connection_flags() not
11585          * torture_open_connection() as the latter forces
11586          * SMB1.
11587          */
11588         if (!torture_open_connection_flags(&cli, 0, 0)) {
11589                 return false;
11590         }
11591
11592         smbXcli_conn_set_sockopt(cli->conn, sockops);
11593
11594         status = cli_list(cli,
11595                         "*",
11596                         FILE_ATTRIBUTE_DIRECTORY,
11597                         msdfs_attribute_list_fn,
11598                         &attr);
11599
11600         if (!NT_STATUS_IS_OK(status)) {
11601                 printf("cli_list failed with %s\n",
11602                         nt_errstr(status));
11603                 goto out;
11604         }
11605         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11606                 printf("file %s should have "
11607                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11608                         test_filename,
11609                         (unsigned int)attr);
11610                 goto out;
11611         }
11612
11613         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11614                 printf("file %s should have "
11615                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11616                         test_filename,
11617                         (unsigned int)attr);
11618                 goto out;
11619         }
11620
11621         correct = true;
11622
11623   out:
11624
11625         torture_close_connection(cli);
11626         return correct;
11627 }
11628
11629 static bool run_cli_echo(int dummy)
11630 {
11631         struct cli_state *cli;
11632         NTSTATUS status;
11633
11634         printf("starting cli_echo test\n");
11635         if (!torture_open_connection(&cli, 0)) {
11636                 return false;
11637         }
11638         smbXcli_conn_set_sockopt(cli->conn, sockops);
11639
11640         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11641
11642         d_printf("cli_echo returned %s\n", nt_errstr(status));
11643
11644         torture_close_connection(cli);
11645         return NT_STATUS_IS_OK(status);
11646 }
11647
11648 static int splice_status(off_t written, void *priv)
11649 {
11650         return true;
11651 }
11652
11653 static bool run_cli_splice(int dummy)
11654 {
11655         uint8_t *buf = NULL;
11656         struct cli_state *cli1 = NULL;
11657         bool correct = false;
11658         const char *fname_src = "\\splice_src.dat";
11659         const char *fname_dst = "\\splice_dst.dat";
11660         NTSTATUS status;
11661         uint16_t fnum1 = UINT16_MAX;
11662         uint16_t fnum2 = UINT16_MAX;
11663         size_t file_size = 2*1024*1024;
11664         size_t splice_size = 1*1024*1024 + 713;
11665         uint8_t digest1[16], digest2[16];
11666         off_t written = 0;
11667         size_t nread = 0;
11668         TALLOC_CTX *frame = talloc_stackframe();
11669
11670         printf("starting cli_splice test\n");
11671
11672         if (!torture_open_connection(&cli1, 0)) {
11673                 goto out;
11674         }
11675
11676         cli_unlink(cli1, fname_src,
11677                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11678         cli_unlink(cli1, fname_dst,
11679                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680
11681         /* Create a file */
11682         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11683                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11684                         0, 0, &fnum1, NULL);
11685
11686         if (!NT_STATUS_IS_OK(status)) {
11687                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11688                 goto out;
11689         }
11690
11691         /* Write file_size bytes - must be bigger than splice_size. */
11692         buf = talloc_zero_array(frame, uint8_t, file_size);
11693         if (buf == NULL) {
11694                 d_printf("talloc_fail\n");
11695                 goto out;
11696         }
11697
11698         /* Fill it with random numbers. */
11699         generate_random_buffer(buf, file_size);
11700
11701         /* MD5 the first 1MB + 713 bytes. */
11702         gnutls_hash_fast(GNUTLS_DIG_MD5,
11703                          buf,
11704                          splice_size,
11705                          digest1);
11706
11707         status = cli_writeall(cli1,
11708                               fnum1,
11709                               0,
11710                               buf,
11711                               0,
11712                               file_size,
11713                               NULL);
11714         if (!NT_STATUS_IS_OK(status)) {
11715                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11716                 goto out;
11717         }
11718
11719         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11720                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11721                         0, 0, &fnum2, NULL);
11722
11723         if (!NT_STATUS_IS_OK(status)) {
11724                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11725                 goto out;
11726         }
11727
11728         /* Now splice 1MB + 713 bytes. */
11729         status = cli_splice(cli1,
11730                                 cli1,
11731                                 fnum1,
11732                                 fnum2,
11733                                 splice_size,
11734                                 0,
11735                                 0,
11736                                 &written,
11737                                 splice_status,
11738                                 NULL);
11739
11740         if (!NT_STATUS_IS_OK(status)) {
11741                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11742                 goto out;
11743         }
11744
11745         /* Clear the old buffer. */
11746         memset(buf, '\0', file_size);
11747
11748         /* Read the new file. */
11749         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11750         if (!NT_STATUS_IS_OK(status)) {
11751                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11752                 goto out;
11753         }
11754         if (nread != splice_size) {
11755                 d_printf("bad read of 0x%x, should be 0x%x\n",
11756                         (unsigned int)nread,
11757                         (unsigned int)splice_size);
11758                 goto out;
11759         }
11760
11761         /* MD5 the first 1MB + 713 bytes. */
11762         gnutls_hash_fast(GNUTLS_DIG_MD5,
11763                          buf,
11764                          splice_size,
11765                          digest2);
11766
11767         /* Must be the same. */
11768         if (memcmp(digest1, digest2, 16) != 0) {
11769                 d_printf("bad MD5 compare\n");
11770                 goto out;
11771         }
11772
11773         correct = true;
11774         printf("Success on cli_splice test\n");
11775
11776   out:
11777
11778         if (cli1) {
11779                 if (fnum1 != UINT16_MAX) {
11780                         cli_close(cli1, fnum1);
11781                 }
11782                 if (fnum2 != UINT16_MAX) {
11783                         cli_close(cli1, fnum2);
11784                 }
11785
11786                 cli_unlink(cli1, fname_src,
11787                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11788                 cli_unlink(cli1, fname_dst,
11789                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11790
11791                 if (!torture_close_connection(cli1)) {
11792                         correct = false;
11793                 }
11794         }
11795
11796         TALLOC_FREE(frame);
11797         return correct;
11798 }
11799
11800 static bool run_uid_regression_test(int dummy)
11801 {
11802         static struct cli_state *cli;
11803         int16_t old_vuid;
11804         int32_t old_cnum;
11805         bool correct = True;
11806         struct smbXcli_tcon *tcon_copy = NULL;
11807         NTSTATUS status;
11808
11809         printf("starting uid regression test\n");
11810
11811         if (!torture_open_connection(&cli, 0)) {
11812                 return False;
11813         }
11814
11815         smbXcli_conn_set_sockopt(cli->conn, sockops);
11816
11817         /* Ok - now save then logoff our current user. */
11818         old_vuid = cli_state_get_uid(cli);
11819
11820         status = cli_ulogoff(cli);
11821         if (!NT_STATUS_IS_OK(status)) {
11822                 d_printf("(%s) cli_ulogoff failed: %s\n",
11823                          __location__, nt_errstr(status));
11824                 correct = false;
11825                 goto out;
11826         }
11827
11828         cli_state_set_uid(cli, old_vuid);
11829
11830         /* Try an operation. */
11831         status = cli_mkdir(cli, "\\uid_reg_test");
11832         if (NT_STATUS_IS_OK(status)) {
11833                 d_printf("(%s) cli_mkdir succeeded\n",
11834                          __location__);
11835                 correct = false;
11836                 goto out;
11837         } else {
11838                 /* Should be bad uid. */
11839                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11840                                  NT_STATUS_USER_SESSION_DELETED)) {
11841                         correct = false;
11842                         goto out;
11843                 }
11844         }
11845
11846         old_cnum = cli_state_get_tid(cli);
11847         /*
11848          * This is an SMB1-only test.
11849          * Copy the tcon, not "save/restore".
11850          *
11851          * In SMB1 the cli_tdis() below frees
11852          * cli->smb1.tcon so we need a copy
11853          * of the struct to put back for the
11854          * second tdis call with invalid vuid.
11855          *
11856          * This is a test-only hack. Real client code
11857          * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11858          */
11859         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11860         if (tcon_copy == NULL) {
11861                 correct = false;
11862                 goto out;
11863         }
11864
11865         /* Now try a SMBtdis with the invalid vuid set to zero. */
11866         cli_state_set_uid(cli, 0);
11867
11868         /* This should succeed. */
11869         status = cli_tdis(cli);
11870
11871         if (NT_STATUS_IS_OK(status)) {
11872                 d_printf("First tdis with invalid vuid should succeed.\n");
11873         } else {
11874                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11875                 correct = false;
11876                 cli->smb1.tcon = tcon_copy;
11877                 goto out;
11878         }
11879
11880         cli->smb1.tcon = tcon_copy;
11881         cli_state_set_uid(cli, old_vuid);
11882         cli_state_set_tid(cli, old_cnum);
11883
11884         /* This should fail. */
11885         status = cli_tdis(cli);
11886         if (NT_STATUS_IS_OK(status)) {
11887                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11888                 correct = false;
11889                 goto out;
11890         } else {
11891                 /* Should be bad tid. */
11892                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11893                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11894                         correct = false;
11895                         goto out;
11896                 }
11897         }
11898
11899         cli_rmdir(cli, "\\uid_reg_test");
11900
11901   out:
11902
11903         cli_shutdown(cli);
11904         return correct;
11905 }
11906
11907
11908 static const char *illegal_chars = "*\\/?<>|\":";
11909 static char force_shortname_chars[] = " +,.[];=\177";
11910
11911 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11912                              const char *mask, void *state)
11913 {
11914         struct cli_state *pcli = (struct cli_state *)state;
11915         fstring fname;
11916         NTSTATUS status = NT_STATUS_OK;
11917
11918         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11919
11920         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11921                 return NT_STATUS_OK;
11922
11923         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11924                 status = cli_rmdir(pcli, fname);
11925                 if (!NT_STATUS_IS_OK(status)) {
11926                         printf("del_fn: failed to rmdir %s\n,", fname );
11927                 }
11928         } else {
11929                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930                 if (!NT_STATUS_IS_OK(status)) {
11931                         printf("del_fn: failed to unlink %s\n,", fname );
11932                 }
11933         }
11934         return status;
11935 }
11936
11937 struct sn_state {
11938         int matched;
11939         int i;
11940         bool val;
11941 };
11942
11943 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11944                               const char *name, void *state)
11945 {
11946         struct sn_state *s = (struct sn_state  *)state;
11947         int i = s->i;
11948
11949 #if 0
11950         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11951                 i, finfo->name, finfo->short_name);
11952 #endif
11953
11954         if (strchr(force_shortname_chars, i)) {
11955                 if (!finfo->short_name) {
11956                         /* Shortname not created when it should be. */
11957                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11958                                 __location__, finfo->name, i);
11959                         s->val = true;
11960                 }
11961         } else if (finfo->short_name){
11962                 /* Shortname created when it should not be. */
11963                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11964                         __location__, finfo->short_name, finfo->name);
11965                 s->val = true;
11966         }
11967         s->matched += 1;
11968         return NT_STATUS_OK;
11969 }
11970
11971 static bool run_shortname_test(int dummy)
11972 {
11973         static struct cli_state *cli;
11974         bool correct = True;
11975         int i;
11976         struct sn_state s;
11977         char fname[40];
11978         NTSTATUS status;
11979
11980         printf("starting shortname test\n");
11981
11982         if (!torture_open_connection(&cli, 0)) {
11983                 return False;
11984         }
11985
11986         smbXcli_conn_set_sockopt(cli->conn, sockops);
11987
11988         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11989         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11990         cli_rmdir(cli, "\\shortname");
11991
11992         status = cli_mkdir(cli, "\\shortname");
11993         if (!NT_STATUS_IS_OK(status)) {
11994                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11995                         __location__, nt_errstr(status));
11996                 correct = false;
11997                 goto out;
11998         }
11999
12000         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12001                 correct = false;
12002                 goto out;
12003         }
12004         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12005                 correct = false;
12006                 goto out;
12007         }
12008
12009         s.val = false;
12010
12011         for (i = 32; i < 128; i++) {
12012                 uint16_t fnum = (uint16_t)-1;
12013
12014                 s.i = i;
12015
12016                 if (strchr(illegal_chars, i)) {
12017                         continue;
12018                 }
12019                 fname[15] = i;
12020
12021                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12022                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12023                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12024                 if (!NT_STATUS_IS_OK(status)) {
12025                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12026                                 __location__, fname, nt_errstr(status));
12027                         correct = false;
12028                         goto out;
12029                 }
12030                 cli_close(cli, fnum);
12031
12032                 s.matched = 0;
12033                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12034                                   shortname_list_fn, &s);
12035                 if (s.matched != 1) {
12036                         d_printf("(%s) failed to list %s: %s\n",
12037                                 __location__, fname, nt_errstr(status));
12038                         correct = false;
12039                         goto out;
12040                 }
12041
12042                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12043                 if (!NT_STATUS_IS_OK(status)) {
12044                         d_printf("(%s) failed to delete %s: %s\n",
12045                                 __location__, fname, nt_errstr(status));
12046                         correct = false;
12047                         goto out;
12048                 }
12049
12050                 if (s.val) {
12051                         correct = false;
12052                         goto out;
12053                 }
12054         }
12055
12056   out:
12057
12058         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12059         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12060         cli_rmdir(cli, "\\shortname");
12061         torture_close_connection(cli);
12062         return correct;
12063 }
12064
12065 TLDAPRC callback_code;
12066
12067 static void pagedsearch_cb(struct tevent_req *req)
12068 {
12069         TLDAPRC rc;
12070         struct tldap_message *msg;
12071         char *dn;
12072
12073         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12074         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12075                 d_printf("tldap_search_paged_recv failed: %s\n",
12076                          tldap_rc2string(rc));
12077                 callback_code = rc;
12078                 return;
12079         }
12080         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12081                 TALLOC_FREE(msg);
12082                 return;
12083         }
12084         if (!tldap_entry_dn(msg, &dn)) {
12085                 d_printf("tldap_entry_dn failed\n");
12086                 return;
12087         }
12088         d_printf("%s\n", dn);
12089         TALLOC_FREE(msg);
12090 }
12091
12092 enum tldap_extended_val {
12093         EXTENDED_ZERO = 0,
12094         EXTENDED_ONE = 1,
12095         EXTENDED_NONE = 2,
12096 };
12097
12098 /*
12099  * Construct an extended dn control with either no value, 0 or 1
12100  *
12101  * No value and 0 are equivalent (non-hyphenated GUID)
12102  * 1 has the hyphenated GUID
12103  */
12104 static struct tldap_control *
12105 tldap_build_extended_control(enum tldap_extended_val val)
12106 {
12107         struct tldap_control empty_control;
12108         struct asn1_data *data;
12109
12110         ZERO_STRUCT(empty_control);
12111
12112         if (val != EXTENDED_NONE) {
12113                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12114
12115                 if (!data) {
12116                         return NULL;
12117                 }
12118
12119                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12120                         return NULL;
12121                 }
12122
12123                 if (!asn1_write_Integer(data, (int)val)) {
12124                         return NULL;
12125                 }
12126
12127                 if (!asn1_pop_tag(data)) {
12128                         return NULL;
12129                 }
12130
12131                 if (!asn1_blob(data, &empty_control.value)) {
12132                         return NULL;
12133                 }
12134         }
12135
12136         empty_control.oid = "1.2.840.113556.1.4.529";
12137         empty_control.critical = true;
12138
12139         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12140
12141 }
12142
12143 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12144                                       enum tldap_extended_val control_val)
12145 {
12146         struct tldap_control *control = tldap_build_extended_control(control_val);
12147         char *dn = NULL;
12148         struct tldap_message **msg;
12149         TLDAPRC rc;
12150
12151         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12152                           "(objectClass=*)", NULL, 0, 0,
12153                           control, 1, NULL,
12154                           0, 0, 0, 0, talloc_tos(), &msg);
12155         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12156                 d_printf("tldap_search for domain DN failed: %s\n",
12157                          tldap_errstr(talloc_tos(), ld, rc));
12158                 return false;
12159         }
12160
12161         if (!tldap_entry_dn(msg[0], &dn)) {
12162                 d_printf("tldap_search domain DN fetch failed: %s\n",
12163                          tldap_errstr(talloc_tos(), ld, rc));
12164                 return false;
12165         }
12166
12167         d_printf("%s\n", dn);
12168         {
12169                 uint32_t time_low;
12170                 uint32_t time_mid, time_hi_and_version;
12171                 uint32_t clock_seq[2];
12172                 uint32_t node[6];
12173                 char next;
12174
12175                 switch (control_val) {
12176                 case EXTENDED_NONE:
12177                 case EXTENDED_ZERO:
12178                         /*
12179                          * When reading GUIDs with hyphens, scanf will treat
12180                          * hyphen as a hex character (and counts as part of the
12181                          * width). This creates leftover GUID string which we
12182                          * check will for with 'next' and closing '>'.
12183                          */
12184                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12185                                          &time_low, &time_mid,
12186                                          &time_hi_and_version, &clock_seq[0],
12187                                          &clock_seq[1], &node[0], &node[1],
12188                                          &node[2], &node[3], &node[4],
12189                                          &node[5], &next)) {
12190                                 /* This GUID is good */
12191                         } else {
12192                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12193                                 return false;
12194                         }
12195
12196                         break;
12197                 case EXTENDED_ONE:
12198                         if (12 == sscanf(dn,
12199                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12200                                          &time_low, &time_mid,
12201                                          &time_hi_and_version, &clock_seq[0],
12202                                          &clock_seq[1], &node[0], &node[1],
12203                                          &node[2], &node[3], &node[4],
12204                                          &node[5], &next)) {
12205                                 /* This GUID is good */
12206                         } else {
12207                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12208                                 return false;
12209                         }
12210
12211                         break;
12212                 default:
12213                         return false;
12214                 }
12215         }
12216
12217         return true;
12218 }
12219
12220 static bool run_tldap(int dummy)
12221 {
12222         struct tldap_context *ld;
12223         int fd;
12224         TLDAPRC rc;
12225         NTSTATUS status;
12226         struct sockaddr_storage addr;
12227         struct tevent_context *ev;
12228         struct tevent_req *req;
12229         char *basedn;
12230         const char *filter;
12231
12232         if (!resolve_name(host, &addr, 0, false)) {
12233                 d_printf("could not find host %s\n", host);
12234                 return false;
12235         }
12236         status = open_socket_out(&addr, 389, 9999, &fd);
12237         if (!NT_STATUS_IS_OK(status)) {
12238                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12239                 return false;
12240         }
12241
12242         ld = tldap_context_create(talloc_tos(), fd);
12243         if (ld == NULL) {
12244                 close(fd);
12245                 d_printf("tldap_context_create failed\n");
12246                 return false;
12247         }
12248
12249         rc = tldap_fetch_rootdse(ld);
12250         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12251                 d_printf("tldap_fetch_rootdse failed: %s\n",
12252                          tldap_errstr(talloc_tos(), ld, rc));
12253                 return false;
12254         }
12255
12256         basedn = tldap_talloc_single_attribute(
12257                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12258         if (basedn == NULL) {
12259                 d_printf("no defaultNamingContext\n");
12260                 return false;
12261         }
12262         d_printf("defaultNamingContext: %s\n", basedn);
12263
12264         ev = samba_tevent_context_init(talloc_tos());
12265         if (ev == NULL) {
12266                 d_printf("tevent_context_init failed\n");
12267                 return false;
12268         }
12269
12270         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12271                                loadparm_init_s3(talloc_tos(),
12272                                                 loadparm_s3_helpers()),
12273                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12274
12275         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12276                 d_printf("tldap_gensec_bind failed\n");
12277                 return false;
12278         }
12279
12280         callback_code = TLDAP_SUCCESS;
12281
12282         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12283                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12284                                       NULL, 0, 0,
12285                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12286         if (req == NULL) {
12287                 d_printf("tldap_search_paged_send failed\n");
12288                 return false;
12289         }
12290         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12291
12292         tevent_req_poll(req, ev);
12293
12294         TALLOC_FREE(req);
12295
12296         rc = callback_code;
12297
12298         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12299                 d_printf("tldap_search with paging failed: %s\n",
12300                          tldap_errstr(talloc_tos(), ld, rc));
12301                 return false;
12302         }
12303
12304         /* test search filters against rootDSE */
12305         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12306                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12307
12308         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12309                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12310                           talloc_tos(), NULL);
12311         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12312                 d_printf("tldap_search with complex filter failed: %s\n",
12313                          tldap_errstr(talloc_tos(), ld, rc));
12314                 return false;
12315         }
12316
12317         /*
12318          * Tests to check for regression of:
12319          *
12320          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12321          *
12322          * TLDAP used here to pick apart the original string DN (with GUID)
12323          */
12324         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12325                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12326                          tldap_errstr(talloc_tos(), ld, rc));
12327                 return false;
12328         }
12329         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12330                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12331                          tldap_errstr(talloc_tos(), ld, rc));
12332                 return false;
12333         }
12334         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12335                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12336                          tldap_errstr(talloc_tos(), ld, rc));
12337                 return false;
12338         }
12339
12340         TALLOC_FREE(ld);
12341         return true;
12342 }
12343
12344 /* Torture test to ensure no regression of :
12345 https://bugzilla.samba.org/show_bug.cgi?id=7084
12346 */
12347
12348 static bool run_dir_createtime(int dummy)
12349 {
12350         struct cli_state *cli;
12351         const char *dname = "\\testdir_createtime";
12352         const char *fname = "\\testdir_createtime\\testfile";
12353         NTSTATUS status;
12354         struct timespec create_time;
12355         struct timespec create_time1;
12356         uint16_t fnum;
12357         bool ret = false;
12358         uint64_t ino;
12359
12360         if (!torture_open_connection(&cli, 0)) {
12361                 return false;
12362         }
12363
12364         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12365                 /* Ensure ino is zero, SMB2 gets a real one. */
12366                 ino = 0;
12367         } else {
12368                 /* Ensure ino is -1, SMB1 never gets a real one. */
12369                 ino = (uint64_t)-1;
12370         }
12371
12372         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12373         cli_rmdir(cli, dname);
12374
12375         status = cli_mkdir(cli, dname);
12376         if (!NT_STATUS_IS_OK(status)) {
12377                 printf("mkdir failed: %s\n", nt_errstr(status));
12378                 goto out;
12379         }
12380
12381         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12382                                 NULL, NULL, &ino);
12383         if (!NT_STATUS_IS_OK(status)) {
12384                 printf("cli_qpathinfo2 returned %s\n",
12385                        nt_errstr(status));
12386                 goto out;
12387         }
12388
12389         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12390                 /* SMB2 should always return an inode. */
12391                 if (ino == 0) {
12392                         printf("SMB2 bad inode (0)\n");
12393                         goto out;
12394                 }
12395         } else {
12396                 /* SMB1 must always return zero here. */
12397                 if (ino != 0) {
12398                         printf("SMB1 bad inode (!0)\n");
12399                         goto out;
12400                 }
12401         }
12402
12403         /* Sleep 3 seconds, then create a file. */
12404         sleep(3);
12405
12406         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12407                          DENY_NONE, &fnum);
12408         if (!NT_STATUS_IS_OK(status)) {
12409                 printf("cli_openx failed: %s\n", nt_errstr(status));
12410                 goto out;
12411         }
12412
12413         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12414                                 NULL, NULL, NULL);
12415         if (!NT_STATUS_IS_OK(status)) {
12416                 printf("cli_qpathinfo2 (2) returned %s\n",
12417                        nt_errstr(status));
12418                 goto out;
12419         }
12420
12421         if (timespec_compare(&create_time1, &create_time)) {
12422                 printf("run_dir_createtime: create time was updated (error)\n");
12423         } else {
12424                 printf("run_dir_createtime: create time was not updated (correct)\n");
12425                 ret = true;
12426         }
12427
12428   out:
12429
12430         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12431         cli_rmdir(cli, dname);
12432         if (!torture_close_connection(cli)) {
12433                 ret = false;
12434         }
12435         return ret;
12436 }
12437
12438
12439 static bool run_streamerror(int dummy)
12440 {
12441         struct cli_state *cli;
12442         const char *dname = "\\testdir_streamerror";
12443         const char *streamname =
12444                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12445         NTSTATUS status;
12446         time_t change_time, access_time, write_time;
12447         off_t size;
12448         uint16_t fnum;
12449         uint32_t attr;
12450         bool ret = true;
12451
12452         if (!torture_open_connection(&cli, 0)) {
12453                 return false;
12454         }
12455
12456         torture_deltree(cli, dname);
12457
12458         status = cli_mkdir(cli, dname);
12459         if (!NT_STATUS_IS_OK(status)) {
12460                 printf("mkdir failed: %s\n", nt_errstr(status));
12461                 return false;
12462         }
12463
12464         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12465                                 &write_time, &size, &attr);
12466         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12467                 printf("pathinfo returned %s, expected "
12468                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12469                        nt_errstr(status));
12470                 ret = false;
12471         }
12472
12473         status = cli_ntcreate(cli, streamname, 0x16,
12474                               FILE_READ_DATA|FILE_READ_EA|
12475                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12476                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12477                               FILE_OPEN, 0, 0, &fnum, NULL);
12478
12479         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12480                 printf("ntcreate returned %s, expected "
12481                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12482                        nt_errstr(status));
12483                 ret = false;
12484         }
12485
12486
12487         cli_rmdir(cli, dname);
12488         return ret;
12489 }
12490
12491 struct pidtest_state {
12492         bool success;
12493         uint16_t vwv[1];
12494         DATA_BLOB data;
12495 };
12496
12497 static void pid_echo_done(struct tevent_req *subreq);
12498
12499 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12500                         struct tevent_context *ev,
12501                         struct cli_state *cli)
12502 {
12503         struct tevent_req *req, *subreq;
12504         struct pidtest_state *state;
12505
12506         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12507         if (req == NULL) {
12508                 return NULL;
12509         }
12510
12511         SSVAL(state->vwv, 0, 1);
12512         state->data = data_blob_const("hello", 5);
12513
12514         subreq = smb1cli_req_send(state,
12515                                 ev,
12516                                 cli->conn,
12517                                 SMBecho,
12518                                 0, 0, /* *_flags */
12519                                 0, 0, /* *_flags2 */
12520                                 cli->timeout,
12521                                 0xDEADBEEF, /* pid */
12522                                 NULL, /* tcon */
12523                                 NULL, /* session */
12524                                 ARRAY_SIZE(state->vwv), state->vwv,
12525                                 state->data.length, state->data.data);
12526
12527         if (tevent_req_nomem(subreq, req)) {
12528                 return tevent_req_post(req, ev);
12529         }
12530         tevent_req_set_callback(subreq, pid_echo_done, req);
12531         return req;
12532 }
12533
12534 static void pid_echo_done(struct tevent_req *subreq)
12535 {
12536         struct tevent_req *req = tevent_req_callback_data(
12537                 subreq, struct tevent_req);
12538         struct pidtest_state *state = tevent_req_data(
12539                 req, struct pidtest_state);
12540         NTSTATUS status;
12541         uint32_t num_bytes;
12542         uint8_t *bytes = NULL;
12543         struct iovec *recv_iov = NULL;
12544         uint8_t *phdr = NULL;
12545         uint16_t pidlow = 0;
12546         uint16_t pidhigh = 0;
12547         struct smb1cli_req_expected_response expected[] = {
12548         {
12549                 .status = NT_STATUS_OK,
12550                 .wct    = 1,
12551         },
12552         };
12553
12554         status = smb1cli_req_recv(subreq, state,
12555                                 &recv_iov,
12556                                 &phdr,
12557                                 NULL, /* pwct */
12558                                 NULL, /* pvwv */
12559                                 NULL, /* pvwv_offset */
12560                                 &num_bytes,
12561                                 &bytes,
12562                                 NULL, /* pbytes_offset */
12563                                 NULL, /* pinbuf */
12564                                 expected, ARRAY_SIZE(expected));
12565
12566         TALLOC_FREE(subreq);
12567
12568         if (!NT_STATUS_IS_OK(status)) {
12569                 tevent_req_nterror(req, status);
12570                 return;
12571         }
12572
12573         if (num_bytes != state->data.length) {
12574                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12575                 return;
12576         }
12577
12578         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12579                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12580                 return;
12581         }
12582
12583         /* Check pid low/high == DEADBEEF */
12584         pidlow = SVAL(phdr, HDR_PID);
12585         if (pidlow != 0xBEEF){
12586                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12587                         (unsigned int)pidlow);
12588                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12589                 return;
12590         }
12591         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12592         if (pidhigh != 0xDEAD){
12593                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12594                         (unsigned int)pidhigh);
12595                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12596                 return;
12597         }
12598
12599         tevent_req_done(req);
12600 }
12601
12602 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12603 {
12604         return tevent_req_simple_recv_ntstatus(req);
12605 }
12606
12607 static bool run_pidhigh(int dummy)
12608 {
12609         bool success = false;
12610         struct cli_state *cli = NULL;
12611         NTSTATUS status;
12612         struct tevent_context *ev = NULL;
12613         struct tevent_req *req = NULL;
12614         TALLOC_CTX *frame = talloc_stackframe();
12615
12616         printf("starting pid high test\n");
12617         if (!torture_open_connection(&cli, 0)) {
12618                 return false;
12619         }
12620         smbXcli_conn_set_sockopt(cli->conn, sockops);
12621
12622         ev = samba_tevent_context_init(frame);
12623         if (ev == NULL) {
12624                 goto fail;
12625         }
12626
12627         req = pid_echo_send(frame, ev, cli);
12628         if (req == NULL) {
12629                 goto fail;
12630         }
12631
12632         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12633                 goto fail;
12634         }
12635
12636         status = pid_echo_recv(req);
12637         if (NT_STATUS_IS_OK(status)) {
12638                 printf("pid high test ok\n");
12639                 success = true;
12640         }
12641
12642  fail:
12643
12644         TALLOC_FREE(frame);
12645         torture_close_connection(cli);
12646         return success;
12647 }
12648
12649 /*
12650   Test Windows open on a bad POSIX symlink.
12651  */
12652 static bool run_symlink_open_test(int dummy)
12653 {
12654         static struct cli_state *cli;
12655         const char *fname = "non_existant_file";
12656         const char *sname = "dangling_symlink";
12657         uint16_t fnum = (uint16_t)-1;
12658         bool correct = false;
12659         NTSTATUS status;
12660         TALLOC_CTX *frame = NULL;
12661
12662         frame = talloc_stackframe();
12663
12664         printf("Starting Windows bad symlink open test\n");
12665
12666         if (!torture_open_connection(&cli, 0)) {
12667                 TALLOC_FREE(frame);
12668                 return false;
12669         }
12670
12671         smbXcli_conn_set_sockopt(cli->conn, sockops);
12672
12673         status = torture_setup_unix_extensions(cli);
12674         if (!NT_STATUS_IS_OK(status)) {
12675                 TALLOC_FREE(frame);
12676                 return false;
12677         }
12678
12679         /* Ensure nothing exists. */
12680         cli_setatr(cli, fname, 0, 0);
12681         cli_posix_unlink(cli, fname);
12682         cli_setatr(cli, sname, 0, 0);
12683         cli_posix_unlink(cli, sname);
12684
12685         /* Create a symlink pointing nowhere. */
12686         status = cli_posix_symlink(cli, fname, sname);
12687         if (!NT_STATUS_IS_OK(status)) {
12688                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12689                         sname,
12690                         fname,
12691                         nt_errstr(status));
12692                 goto out;
12693         }
12694
12695         /* Now ensure that a Windows open doesn't hang. */
12696         status = cli_ntcreate(cli,
12697                         sname,
12698                         0,
12699                         FILE_READ_DATA|FILE_WRITE_DATA,
12700                         0,
12701                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12702                         FILE_OPEN_IF,
12703                         0x0,
12704                         0x0,
12705                         &fnum,
12706                         NULL);
12707
12708         /*
12709          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12710          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12711          * we use O_NOFOLLOW on the server or not.
12712          */
12713         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12714             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12715         {
12716                 correct = true;
12717         } else {
12718                 printf("cli_ntcreate of %s returned %s - should return"
12719                                 " either (%s) or (%s)\n",
12720                         sname,
12721                         nt_errstr(status),
12722                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12723                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12724                 goto out;
12725         }
12726
12727         correct = true;
12728
12729   out:
12730
12731         if (fnum != (uint16_t)-1) {
12732                 cli_close(cli, fnum);
12733                 fnum = (uint16_t)-1;
12734         }
12735
12736         cli_setatr(cli, sname, 0, 0);
12737         cli_posix_unlink(cli, sname);
12738         cli_setatr(cli, fname, 0, 0);
12739         cli_posix_unlink(cli, fname);
12740
12741         if (!torture_close_connection(cli)) {
12742                 correct = false;
12743         }
12744
12745         TALLOC_FREE(frame);
12746         return correct;
12747 }
12748
12749 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12750                                         const char *name,
12751                                         void *state)
12752 {
12753         char **mangled_name_return = (char **)state;
12754         bool is_mangled = strchr(finfo->name, '~');
12755
12756         if (is_mangled) {
12757                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12758                 if (*mangled_name_return == NULL) {
12759                         return NT_STATUS_NO_MEMORY;
12760                 }
12761         }
12762         return NT_STATUS_OK;
12763 }
12764
12765 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12766 {
12767         static struct cli_state *cli_posix = NULL;
12768         static struct cli_state *cli = NULL;
12769         uint16_t fnum = (uint16_t)-1;
12770         bool correct = false;
12771         const char *dname = "smb1_wild_mangle_unlink";
12772         const char *aname = "smb1_wild_mangle_unlink/a";
12773         const char *star_name = "smb1_wild_mangle_unlink/*";
12774         char *windows_unlink_name = NULL;
12775         char *mangled_name = NULL;
12776         NTSTATUS status;
12777
12778         printf("Starting SMB1 wild mangle unlink test\n");
12779
12780         /* Open a Windows connection. */
12781         if (!torture_open_connection(&cli, 0)) {
12782                 return false;
12783         }
12784
12785         smbXcli_conn_set_sockopt(cli->conn, sockops);
12786
12787         /* Open a POSIX connection. */
12788         if (!torture_open_connection(&cli_posix, 0)) {
12789                 goto out;
12790         }
12791
12792         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12793
12794         status = torture_setup_unix_extensions(cli_posix);
12795         if (!NT_STATUS_IS_OK(status)) {
12796                 printf("server doesn't support POSIX\n");
12797                 goto out;
12798         }
12799
12800         /* Start fresh. */
12801         torture_deltree(cli, dname);
12802
12803         /*
12804          * Create two files - 'a' and '*'.
12805          * We need POSIX extensions for this as '*'
12806          * is not a valid Windows name.
12807          */
12808
12809         status = cli_mkdir(cli, dname);
12810         if (!NT_STATUS_IS_OK(status)) {
12811                 printf("cli_mkdir of %s returned %s\n",
12812                         dname,
12813                         nt_errstr(status));
12814                 goto out;
12815         }
12816
12817         status = cli_posix_open(cli_posix,
12818                                 aname,
12819                                 O_RDWR|O_CREAT|O_EXCL,
12820                                 0660,
12821                                 &fnum);
12822         if (!NT_STATUS_IS_OK(status)) {
12823                 printf("cli_posix_open (create) of %s returned %s\n",
12824                         aname,
12825                         nt_errstr(status));
12826                 goto out;
12827         }
12828         status = cli_close(cli_posix, fnum);
12829         if (!NT_STATUS_IS_OK(status)) {
12830                 goto out;
12831         }
12832         status = cli_posix_open(cli_posix,
12833                                 star_name,
12834                                 O_RDWR|O_CREAT|O_EXCL,
12835                                 0660,
12836                                 &fnum);
12837         if (!NT_STATUS_IS_OK(status)) {
12838                 printf("cli_posix_open (create) of %s returned %s\n",
12839                         star_name,
12840                         nt_errstr(status));
12841                 goto out;
12842         }
12843         status = cli_close(cli_posix, fnum);
12844         if (!NT_STATUS_IS_OK(status)) {
12845                 goto out;
12846         }
12847
12848         status = cli_list(cli,
12849                         star_name,
12850                         0,
12851                         smb1_wild_mangle_list_fn,
12852                         &mangled_name);
12853         if (!NT_STATUS_IS_OK(status)) {
12854                 printf("cli_list of %s returned %s\n",
12855                         star_name,
12856                         nt_errstr(status));
12857                 goto out;
12858         }
12859
12860         if (mangled_name == NULL) {
12861                 goto out;
12862         }
12863
12864         printf("mangled_name = %s\n",
12865                 mangled_name);
12866
12867         /*
12868          * Try a Windows unlink with the mangled name.
12869          * This should *NOT* unlink the 'a' name.
12870          */
12871
12872         windows_unlink_name = talloc_asprintf(cli_posix,
12873                                         "%s\\%s",
12874                                         dname,
12875                                         mangled_name);
12876
12877         status = cli_unlink(cli, windows_unlink_name, 0);
12878         if (!NT_STATUS_IS_OK(status)) {
12879                 printf("cli_unlink of %s returned %s\n",
12880                         windows_unlink_name,
12881                         nt_errstr(status));
12882                 goto out;
12883         }
12884
12885         /* Does 'a' still exist ? */
12886         status = cli_posix_open(cli_posix,
12887                                 aname,
12888                                 O_RDONLY,
12889                                 0,
12890                                 &fnum);
12891         if (!NT_STATUS_IS_OK(status)) {
12892                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12893                         aname,
12894                         nt_errstr(status));
12895                 goto out;
12896         }
12897
12898         status = cli_close(cli_posix, fnum);
12899         if (!NT_STATUS_IS_OK(status)) {
12900                 goto out;
12901         }
12902
12903         correct = true;
12904
12905   out:
12906
12907         TALLOC_FREE(windows_unlink_name);
12908         TALLOC_FREE(mangled_name);
12909
12910         if (cli != NULL) {
12911                 torture_deltree(cli, dname);
12912                 torture_close_connection(cli);
12913         }
12914
12915         if (cli_posix != NULL) {
12916                 torture_close_connection(cli_posix);
12917         }
12918
12919         return correct;
12920 }
12921
12922 static bool run_smb1_wild_mangle_rename_test(int dummy)
12923 {
12924         static struct cli_state *cli_posix = NULL;
12925         static struct cli_state *cli = NULL;
12926         uint16_t fnum = (uint16_t)-1;
12927         bool correct = false;
12928         const char *dname = "smb1_wild_mangle_rename";
12929         const char *fooname = "smb1_wild_mangle_rename/foo";
12930         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12931         const char *wild_name = "smb1_wild_mangle_rename/*";
12932         char *windows_rename_src = NULL;
12933         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12934         char *mangled_name = NULL;
12935         NTSTATUS status;
12936
12937         printf("Starting SMB1 wild mangle rename test\n");
12938
12939         if (!torture_open_connection(&cli_posix, 0)) {
12940                 return false;
12941         }
12942
12943         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12944
12945         status = torture_setup_unix_extensions(cli_posix);
12946         if (!NT_STATUS_IS_OK(status)) {
12947                 printf("server doesn't support POSIX\n");
12948                 return false;
12949         }
12950
12951         /* Open a Windows connection. */
12952         if (!torture_open_connection(&cli, 0)) {
12953                 goto out;
12954         }
12955
12956         smbXcli_conn_set_sockopt(cli->conn, sockops);
12957
12958         /* Ensure we start from fresh. */
12959         torture_deltree(cli, dname);
12960
12961         /*
12962          * Create two files - 'foo' and 'fo*'.
12963          * We need POSIX extensions for this as 'fo*'
12964          * is not a valid Windows name.
12965          */
12966
12967         status = cli_posix_mkdir(cli_posix, dname, 0770);
12968         if (!NT_STATUS_IS_OK(status)) {
12969                 printf("cli_posix_mkdir of %s returned %s\n",
12970                         dname,
12971                         nt_errstr(status));
12972                 goto out;
12973         }
12974
12975         status = cli_posix_open(cli_posix,
12976                                 fooname,
12977                                 O_RDWR|O_CREAT|O_EXCL,
12978                                 0660,
12979                                 &fnum);
12980         if (!NT_STATUS_IS_OK(status)) {
12981                 printf("cli_posix_open (create) of %s returned %s\n",
12982                         fooname,
12983                         nt_errstr(status));
12984                 goto out;
12985         }
12986         status = cli_close(cli_posix, fnum);
12987         if (!NT_STATUS_IS_OK(status)) {
12988                 goto out;
12989         }
12990         status = cli_posix_open(cli_posix,
12991                                 foostar_name,
12992                                 O_RDWR|O_CREAT|O_EXCL,
12993                                 0660,
12994                                 &fnum);
12995         if (!NT_STATUS_IS_OK(status)) {
12996                 printf("cli_posix_open (create) of %s returned %s\n",
12997                         foostar_name,
12998                         nt_errstr(status));
12999                 goto out;
13000         }
13001         status = cli_close(cli_posix, fnum);
13002         if (!NT_STATUS_IS_OK(status)) {
13003                 goto out;
13004         }
13005
13006         /*
13007          * Get the mangled name. We can re-use the
13008          * previous smb1_wild_mangle_list_fn for this.
13009          */
13010
13011         status = cli_list(cli,
13012                         wild_name,
13013                         0,
13014                         smb1_wild_mangle_list_fn,
13015                         &mangled_name);
13016         if (!NT_STATUS_IS_OK(status)) {
13017                 printf("cli_list of %s returned %s\n",
13018                         wild_name,
13019                         nt_errstr(status));
13020                 goto out;
13021         }
13022
13023         if (mangled_name == NULL) {
13024                 goto out;
13025         }
13026
13027         printf("mangled_name = %s\n",
13028                 mangled_name);
13029
13030         /*
13031          * Try a Windows rename with the mangled name.
13032          * This should *NOT* rename the 'foo' name.
13033          */
13034
13035         windows_rename_src = talloc_asprintf(cli_posix,
13036                                         "%s\\%s",
13037                                         dname,
13038                                         mangled_name);
13039
13040         status = cli_rename(cli,
13041                         windows_rename_src,
13042                         windows_rename_dst,
13043                         false);
13044         if (!NT_STATUS_IS_OK(status)) {
13045                 printf("cli_rename of %s -> %s returned %s\n",
13046                         windows_rename_src,
13047                         windows_rename_dst,
13048                         nt_errstr(status));
13049                 goto out;
13050         }
13051
13052         /* Does 'foo' still exist ? */
13053         status = cli_posix_open(cli_posix,
13054                                 fooname,
13055                                 O_RDONLY,
13056                                 0,
13057                                 &fnum);
13058         if (!NT_STATUS_IS_OK(status)) {
13059                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13060                         fooname,
13061                         nt_errstr(status));
13062                 goto out;
13063         }
13064
13065         status = cli_close(cli_posix, fnum);
13066         if (!NT_STATUS_IS_OK(status)) {
13067                 goto out;
13068         }
13069
13070         correct = true;
13071
13072   out:
13073
13074         TALLOC_FREE(mangled_name);
13075         TALLOC_FREE(windows_rename_src);
13076
13077         if (cli != NULL) {
13078                 torture_deltree(cli, dname);
13079                 torture_close_connection(cli);
13080         }
13081
13082         torture_close_connection(cli_posix);
13083
13084         return correct;
13085 }
13086
13087 /*
13088  * Only testing minimal time strings, as the others
13089  * need (locale-dependent) guessing at what strftime does and
13090  * even may differ in builds.
13091  */
13092 static bool timesubst_test(void)
13093 {
13094         TALLOC_CTX *ctx = NULL;
13095         /* Sa 23. Dez 04:33:20 CET 2017 */
13096         const struct timeval tv = { 1514000000, 123 };
13097         const char* expect_minimal = "20171223_033320";
13098         const char* expect_minus   = "20171223_033320_000123";
13099         char *s;
13100         char *env_tz, *orig_tz = NULL;
13101         bool result = true;
13102
13103         ctx = talloc_new(NULL);
13104
13105         env_tz = getenv("TZ");
13106         if(env_tz) {
13107                 orig_tz = talloc_strdup(ctx, env_tz);
13108         }
13109         setenv("TZ", "UTC", 1);
13110
13111         s = minimal_timeval_string(ctx, &tv, false);
13112
13113         if(!s || strcmp(s, expect_minimal)) {
13114                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13115                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13116                 result = false;
13117         }
13118         TALLOC_FREE(s);
13119         s = minimal_timeval_string(ctx, &tv, true);
13120         if(!s || strcmp(s, expect_minus)) {
13121                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13122                        "[%s]\n", s ? s : "<nil>", expect_minus);
13123                 result = false;
13124         }
13125         TALLOC_FREE(s);
13126
13127         if(orig_tz) {
13128                 setenv("TZ", orig_tz, 1);
13129         }
13130
13131         TALLOC_FREE(ctx);
13132         return result;
13133 }
13134
13135 static bool run_local_substitute(int dummy)
13136 {
13137         bool ok = true;
13138
13139         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13140         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13141         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13142         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13143         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13144         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13145         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13146         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13147         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13148         /* Substitution depends on current time, so better test the underlying
13149            formatting function. At least covers %t. */
13150         ok &= timesubst_test();
13151
13152         /* Different captialization rules in sub_basic... */
13153
13154         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13155                        "blaDOM") == 0);
13156
13157         return ok;
13158 }
13159
13160 static bool run_local_base64(int dummy)
13161 {
13162         int i;
13163         bool ret = true;
13164
13165         for (i=1; i<2000; i++) {
13166                 DATA_BLOB blob1, blob2;
13167                 char *b64;
13168
13169                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13170                 blob1.length = i;
13171                 generate_random_buffer(blob1.data, blob1.length);
13172
13173                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13174                 if (b64 == NULL) {
13175                         d_fprintf(stderr, "base64_encode_data_blob failed "
13176                                   "for %d bytes\n", i);
13177                         ret = false;
13178                 }
13179                 blob2 = base64_decode_data_blob(b64);
13180                 TALLOC_FREE(b64);
13181
13182                 if (data_blob_cmp(&blob1, &blob2)) {
13183                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13184                                   "bytes\n", i);
13185                         ret = false;
13186                 }
13187                 TALLOC_FREE(blob1.data);
13188                 data_blob_free(&blob2);
13189         }
13190         return ret;
13191 }
13192
13193 static void parse_fn(const struct gencache_timeout *t,
13194                      DATA_BLOB blob,
13195                      void *private_data)
13196 {
13197         return;
13198 }
13199
13200 static bool run_local_gencache(int dummy)
13201 {
13202         char *val;
13203         time_t tm;
13204         DATA_BLOB blob;
13205         char v;
13206         struct memcache *mem;
13207         int i;
13208
13209         mem = memcache_init(NULL, 0);
13210         if (mem == NULL) {
13211                 d_printf("%s: memcache_init failed\n", __location__);
13212                 return false;
13213         }
13214         memcache_set_global(mem);
13215
13216         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13217                 d_printf("%s: gencache_set() failed\n", __location__);
13218                 return False;
13219         }
13220
13221         if (!gencache_get("foo", NULL, NULL, NULL)) {
13222                 d_printf("%s: gencache_get() failed\n", __location__);
13223                 return False;
13224         }
13225
13226         for (i=0; i<1000000; i++) {
13227                 gencache_parse("foo", parse_fn, NULL);
13228         }
13229
13230         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13231                 d_printf("%s: gencache_get() failed\n", __location__);
13232                 return False;
13233         }
13234         TALLOC_FREE(val);
13235
13236         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13237                 d_printf("%s: gencache_get() failed\n", __location__);
13238                 return False;
13239         }
13240
13241         if (strcmp(val, "bar") != 0) {
13242                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13243                          __location__, val, "bar");
13244                 TALLOC_FREE(val);
13245                 return False;
13246         }
13247
13248         TALLOC_FREE(val);
13249
13250         if (!gencache_del("foo")) {
13251                 d_printf("%s: gencache_del() failed\n", __location__);
13252                 return False;
13253         }
13254         if (gencache_del("foo")) {
13255                 d_printf("%s: second gencache_del() succeeded\n",
13256                          __location__);
13257                 return False;
13258         }
13259
13260         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13261                 d_printf("%s: gencache_get() on deleted entry "
13262                          "succeeded\n", __location__);
13263                 return False;
13264         }
13265
13266         blob = data_blob_string_const_null("bar");
13267         tm = time(NULL) + 60;
13268
13269         if (!gencache_set_data_blob("foo", blob, tm)) {
13270                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13271                 return False;
13272         }
13273
13274         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13275                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13276                 return False;
13277         }
13278
13279         if (strcmp((const char *)blob.data, "bar") != 0) {
13280                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13281                          __location__, (const char *)blob.data, "bar");
13282                 data_blob_free(&blob);
13283                 return False;
13284         }
13285
13286         data_blob_free(&blob);
13287
13288         if (!gencache_del("foo")) {
13289                 d_printf("%s: gencache_del() failed\n", __location__);
13290                 return False;
13291         }
13292         if (gencache_del("foo")) {
13293                 d_printf("%s: second gencache_del() succeeded\n",
13294                          __location__);
13295                 return False;
13296         }
13297
13298         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13299                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13300                          "succeeded\n", __location__);
13301                 return False;
13302         }
13303
13304         v = 1;
13305         blob.data = (uint8_t *)&v;
13306         blob.length = sizeof(v);
13307
13308         if (!gencache_set_data_blob("blob", blob, tm)) {
13309                 d_printf("%s: gencache_set_data_blob() failed\n",
13310                          __location__);
13311                 return false;
13312         }
13313         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13314                 d_printf("%s: gencache_get succeeded\n", __location__);
13315                 return false;
13316         }
13317
13318         return True;
13319 }
13320
13321 static bool rbt_testflags(struct db_context *db, const char *key,
13322                           const char *value)
13323 {
13324         bool ret = false;
13325         NTSTATUS status;
13326         struct db_record *rec;
13327
13328         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13329         if (rec == NULL) {
13330                 d_fprintf(stderr, "fetch_locked failed\n");
13331                 goto done;
13332         }
13333
13334         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13335         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13336                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13337                           nt_errstr(status));
13338                 goto done;
13339         }
13340
13341         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13342                                      TDB_INSERT);
13343         if (!NT_STATUS_IS_OK(status)) {
13344                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13345                           nt_errstr(status));
13346                 goto done;
13347         }
13348
13349         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13350         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13351                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13352                           nt_errstr(status));
13353                 goto done;
13354         }
13355
13356         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13357         if (!NT_STATUS_IS_OK(status)) {
13358                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13359                           nt_errstr(status));
13360                 goto done;
13361         }
13362
13363         ret = true;
13364 done:
13365         TALLOC_FREE(rec);
13366         return ret;
13367 }
13368
13369 static bool rbt_testval(struct db_context *db, const char *key,
13370                         const char *value)
13371 {
13372         struct db_record *rec;
13373         TDB_DATA data = string_tdb_data(value);
13374         bool ret = false;
13375         NTSTATUS status;
13376         TDB_DATA dbvalue;
13377
13378         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13379         if (rec == NULL) {
13380                 d_fprintf(stderr, "fetch_locked failed\n");
13381                 goto done;
13382         }
13383         status = dbwrap_record_store(rec, data, 0);
13384         if (!NT_STATUS_IS_OK(status)) {
13385                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13386                 goto done;
13387         }
13388         TALLOC_FREE(rec);
13389
13390         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13391         if (rec == NULL) {
13392                 d_fprintf(stderr, "second fetch_locked failed\n");
13393                 goto done;
13394         }
13395
13396         dbvalue = dbwrap_record_get_value(rec);
13397         if ((dbvalue.dsize != data.dsize)
13398             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13399                 d_fprintf(stderr, "Got wrong data back\n");
13400                 goto done;
13401         }
13402
13403         ret = true;
13404  done:
13405         TALLOC_FREE(rec);
13406         return ret;
13407 }
13408
13409 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13410 {
13411         int *count2 = (int *)private_data;
13412         (*count2)++;
13413         return 0;
13414 }
13415
13416 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13417 {
13418         int *count2 = (int *)private_data;
13419         (*count2)++;
13420         dbwrap_record_delete(rec);
13421         return 0;
13422 }
13423
13424 static bool run_local_rbtree(int dummy)
13425 {
13426         struct db_context *db;
13427         bool ret = false;
13428         int i;
13429         NTSTATUS status;
13430         int count = 0;
13431         int count2 = 0;
13432
13433         db = db_open_rbt(NULL);
13434
13435         if (db == NULL) {
13436                 d_fprintf(stderr, "db_open_rbt failed\n");
13437                 return false;
13438         }
13439
13440         if (!rbt_testflags(db, "firstkey", "firstval")) {
13441                 goto done;
13442         }
13443
13444         for (i = 0; i < 999; i++) {
13445                 char key[sizeof("key-9223372036854775807")];
13446                 char value[sizeof("value-9223372036854775807")];
13447
13448                 snprintf(key, sizeof(key), "key%ld", random());
13449                 snprintf(value, sizeof(value) ,"value%ld", random());
13450
13451                 if (!rbt_testval(db, key, value)) {
13452                         goto done;
13453                 }
13454
13455                 snprintf(value, sizeof(value) ,"value%ld", random());
13456
13457                 if (!rbt_testval(db, key, value)) {
13458                         goto done;
13459                 }
13460         }
13461
13462         ret = true;
13463         count = 0; count2 = 0;
13464         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13465                                       &count2, &count);
13466         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13467         if ((count != count2) || (count != 1000)) {
13468                 ret = false;
13469         }
13470         count = 0; count2 = 0;
13471         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13472                                  &count2, &count);
13473         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13474         if ((count != count2) || (count != 1000)) {
13475                 ret = false;
13476         }
13477         count = 0; count2 = 0;
13478         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13479                                       &count2, &count);
13480         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13481         if ((count != count2) || (count != 0)) {
13482                 ret = false;
13483         }
13484
13485  done:
13486         TALLOC_FREE(db);
13487         return ret;
13488 }
13489
13490
13491 /*
13492   local test for character set functions
13493
13494   This is a very simple test for the functionality in convert_string_error()
13495  */
13496 static bool run_local_convert_string(int dummy)
13497 {
13498         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13499         const char *test_strings[2] = { "March", "M\303\244rz" };
13500         char dst[7];
13501         int i;
13502
13503         for (i=0; i<2; i++) {
13504                 const char *str = test_strings[i];
13505                 int len = strlen(str);
13506                 size_t converted_size;
13507                 bool ret;
13508
13509                 memset(dst, 'X', sizeof(dst));
13510
13511                 /* first try with real source length */
13512                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13513                                            str, len,
13514                                            dst, sizeof(dst),
13515                                            &converted_size);
13516                 if (ret != true) {
13517                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13518                         goto failed;
13519                 }
13520
13521                 if (converted_size != len) {
13522                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13523                                   str, len, (int)converted_size);
13524                         goto failed;
13525                 }
13526
13527                 if (strncmp(str, dst, converted_size) != 0) {
13528                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13529                         goto failed;
13530                 }
13531
13532                 if (strlen(str) != converted_size) {
13533                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13534                                   (int)strlen(str), (int)converted_size);
13535                         goto failed;
13536                 }
13537
13538                 if (dst[converted_size] != 'X') {
13539                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13540                         goto failed;
13541                 }
13542
13543                 /* now with srclen==-1, this causes the nul to be
13544                  * converted too */
13545                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13546                                            str, -1,
13547                                            dst, sizeof(dst),
13548                                            &converted_size);
13549                 if (ret != true) {
13550                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13551                         goto failed;
13552                 }
13553
13554                 if (converted_size != len+1) {
13555                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13556                                   str, len, (int)converted_size);
13557                         goto failed;
13558                 }
13559
13560                 if (strncmp(str, dst, converted_size) != 0) {
13561                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13562                         goto failed;
13563                 }
13564
13565                 if (len+1 != converted_size) {
13566                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13567                                   len+1, (int)converted_size);
13568                         goto failed;
13569                 }
13570
13571                 if (dst[converted_size] != 'X') {
13572                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13573                         goto failed;
13574                 }
13575
13576         }
13577
13578
13579         TALLOC_FREE(tmp_ctx);
13580         return true;
13581 failed:
13582         TALLOC_FREE(tmp_ctx);
13583         return false;
13584 }
13585
13586 static bool run_local_string_to_sid(int dummy) {
13587         struct dom_sid sid;
13588
13589         if (string_to_sid(&sid, "S--1-5-32-545")) {
13590                 printf("allowing S--1-5-32-545\n");
13591                 return false;
13592         }
13593         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13594                 printf("allowing S-1-5-32-+545\n");
13595                 return false;
13596         }
13597         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")) {
13598                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13599                 return false;
13600         }
13601         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13602                 printf("allowing S-1-5-32-545-abc\n");
13603                 return false;
13604         }
13605         if (string_to_sid(&sid, "S-300-5-32-545")) {
13606                 printf("allowing S-300-5-32-545\n");
13607                 return false;
13608         }
13609         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13610                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13611                 return false;
13612         }
13613         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13614                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13615                 return false;
13616         }
13617         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13618                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13619                 return false;
13620         }
13621         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13622                 printf("could not parse S-1-5-32-545\n");
13623                 return false;
13624         }
13625         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13626                 struct dom_sid_buf buf;
13627                 printf("mis-parsed S-1-5-32-545 as %s\n",
13628                        dom_sid_str_buf(&sid, &buf));
13629                 return false;
13630         }
13631         return true;
13632 }
13633
13634 static bool sid_to_string_test(const char *expected) {
13635         char *str;
13636         bool res = true;
13637         struct dom_sid sid;
13638
13639         if (!string_to_sid(&sid, expected)) {
13640                 printf("could not parse %s\n", expected);
13641                 return false;
13642         }
13643
13644         str = dom_sid_string(NULL, &sid);
13645         if (strcmp(str, expected)) {
13646                 printf("Comparison failed (%s != %s)\n", str, expected);
13647                 res = false;
13648         }
13649         TALLOC_FREE(str);
13650         return res;
13651 }
13652
13653 static bool run_local_sid_to_string(int dummy) {
13654         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13655                 return false;
13656         if (!sid_to_string_test("S-1-545"))
13657                 return false;
13658         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13659                 return false;
13660         return true;
13661 }
13662
13663 static bool run_local_binary_to_sid(int dummy) {
13664         ssize_t ret;
13665         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13666         static const uint8_t good_binary_sid[] = {
13667                 0x1, /* revision number */
13668                 15, /* num auths */
13669                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13670                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13671                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13672                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13673                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13674                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13675                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13676                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13677                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13678                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13679                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13680                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13681                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13682                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13683                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13684                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13685         };
13686
13687         static const uint8_t long_binary_sid[] = {
13688                 0x1, /* revision number */
13689                 15, /* num auths */
13690                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13691                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13692                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13693                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13694                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13695                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13696                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13697                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13698                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13699                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13700                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13701                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13702                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13703                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13704                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13705                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13706                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13707                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13708                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13709         };
13710
13711         static const uint8_t long_binary_sid2[] = {
13712                 0x1, /* revision number */
13713                 32, /* num auths */
13714                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13715                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13716                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13717                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13718                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13719                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13720                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13721                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13722                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13723                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13724                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13725                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13726                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13727                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13728                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13729                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13730                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13731                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13732                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13733                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13734                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13735                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13736                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13737                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13738                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13739                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13740                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13741                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13742                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13743                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13744                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13745                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13746                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13747         };
13748
13749         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13750         if (ret == -1) {
13751                 return false;
13752         }
13753         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13754         if (ret != -1) {
13755                 return false;
13756         }
13757         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13758         if (ret != -1) {
13759                 return false;
13760         }
13761         return true;
13762 }
13763
13764 /* Split a path name into filename and stream name components. Canonicalise
13765  * such that an implicit $DATA token is always explicit.
13766  *
13767  * The "specification" of this function can be found in the
13768  * run_local_stream_name() function in torture.c, I've tried those
13769  * combinations against a W2k3 server.
13770  */
13771
13772 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13773                                        char **pbase, char **pstream)
13774 {
13775         char *base = NULL;
13776         char *stream = NULL;
13777         char *sname; /* stream name */
13778         const char *stype; /* stream type */
13779
13780         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13781
13782         sname = strchr_m(fname, ':');
13783
13784         if (sname == NULL) {
13785                 if (pbase != NULL) {
13786                         base = talloc_strdup(mem_ctx, fname);
13787                         NT_STATUS_HAVE_NO_MEMORY(base);
13788                 }
13789                 goto done;
13790         }
13791
13792         if (pbase != NULL) {
13793                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13794                 NT_STATUS_HAVE_NO_MEMORY(base);
13795         }
13796
13797         sname += 1;
13798
13799         stype = strchr_m(sname, ':');
13800
13801         if (stype == NULL) {
13802                 sname = talloc_strdup(mem_ctx, sname);
13803                 stype = "$DATA";
13804         }
13805         else {
13806                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13807                         /*
13808                          * If there is an explicit stream type, so far we only
13809                          * allow $DATA. Is there anything else allowed? -- vl
13810                          */
13811                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13812                         TALLOC_FREE(base);
13813                         return NT_STATUS_OBJECT_NAME_INVALID;
13814                 }
13815                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13816                 stype += 1;
13817         }
13818
13819         if (sname == NULL) {
13820                 TALLOC_FREE(base);
13821                 return NT_STATUS_NO_MEMORY;
13822         }
13823
13824         if (sname[0] == '\0') {
13825                 /*
13826                  * no stream name, so no stream
13827                  */
13828                 goto done;
13829         }
13830
13831         if (pstream != NULL) {
13832                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13833                 if (stream == NULL) {
13834                         TALLOC_FREE(sname);
13835                         TALLOC_FREE(base);
13836                         return NT_STATUS_NO_MEMORY;
13837                 }
13838                 /*
13839                  * upper-case the type field
13840                  */
13841                 (void)strupper_m(strchr_m(stream, ':')+1);
13842         }
13843
13844  done:
13845         if (pbase != NULL) {
13846                 *pbase = base;
13847         }
13848         if (pstream != NULL) {
13849                 *pstream = stream;
13850         }
13851         return NT_STATUS_OK;
13852 }
13853
13854 static bool test_stream_name(const char *fname, const char *expected_base,
13855                              const char *expected_stream,
13856                              NTSTATUS expected_status)
13857 {
13858         NTSTATUS status;
13859         char *base = NULL;
13860         char *stream = NULL;
13861
13862         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13863         if (!NT_STATUS_EQUAL(status, expected_status)) {
13864                 goto error;
13865         }
13866
13867         if (!NT_STATUS_IS_OK(status)) {
13868                 return true;
13869         }
13870
13871         if (base == NULL) goto error;
13872
13873         if (strcmp(expected_base, base) != 0) goto error;
13874
13875         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13876         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13877
13878         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13879                 goto error;
13880
13881         TALLOC_FREE(base);
13882         TALLOC_FREE(stream);
13883         return true;
13884
13885  error:
13886         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13887                   fname, expected_base ? expected_base : "<NULL>",
13888                   expected_stream ? expected_stream : "<NULL>",
13889                   nt_errstr(expected_status));
13890         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13891                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13892                   nt_errstr(status));
13893         TALLOC_FREE(base);
13894         TALLOC_FREE(stream);
13895         return false;
13896 }
13897
13898 static bool run_local_stream_name(int dummy)
13899 {
13900         bool ret = true;
13901
13902         ret &= test_stream_name(
13903                 "bla", "bla", NULL, NT_STATUS_OK);
13904         ret &= test_stream_name(
13905                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13906         ret &= test_stream_name(
13907                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13908         ret &= test_stream_name(
13909                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13910         ret &= test_stream_name(
13911                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13912         ret &= test_stream_name(
13913                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13914         ret &= test_stream_name(
13915                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13916         ret &= test_stream_name(
13917                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13918
13919         return ret;
13920 }
13921
13922 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13923 {
13924         if (a.length != b.length) {
13925                 printf("a.length=%d != b.length=%d\n",
13926                        (int)a.length, (int)b.length);
13927                 return false;
13928         }
13929         if (memcmp(a.data, b.data, a.length) != 0) {
13930                 printf("a.data and b.data differ\n");
13931                 return false;
13932         }
13933         return true;
13934 }
13935
13936 static bool run_local_memcache(int dummy)
13937 {
13938         struct memcache *cache;
13939         DATA_BLOB k1, k2, k3, k4, k5;
13940         DATA_BLOB d1, d3;
13941         DATA_BLOB v1, v3;
13942
13943         TALLOC_CTX *mem_ctx;
13944         char *ptr1 = NULL;
13945         char *ptr2 = NULL;
13946         char *ptr3 = NULL;
13947
13948         char *str1, *str2;
13949         size_t size1, size2;
13950         bool ret = false;
13951
13952         mem_ctx = talloc_init("foo");
13953         if (mem_ctx == NULL) {
13954                 return false;
13955         }
13956
13957         /* STAT_CACHE TESTS */
13958
13959         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13960
13961         if (cache == NULL) {
13962                 printf("memcache_init failed\n");
13963                 return false;
13964         }
13965
13966         d1 = data_blob_const("d1", 2);
13967         d3 = data_blob_const("d3", 2);
13968
13969         k1 = data_blob_const("d1", 2);
13970         k2 = data_blob_const("d2", 2);
13971         k3 = data_blob_const("d3", 2);
13972         k4 = data_blob_const("d4", 2);
13973         k5 = data_blob_const("d5", 2);
13974
13975         memcache_add(cache, STAT_CACHE, k1, d1);
13976
13977         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13978                 printf("could not find k1\n");
13979                 return false;
13980         }
13981         if (!data_blob_equal(d1, v1)) {
13982                 return false;
13983         }
13984
13985         memcache_add(cache, STAT_CACHE, k1, d3);
13986
13987         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13988                 printf("could not find replaced k1\n");
13989                 return false;
13990         }
13991         if (!data_blob_equal(d3, v3)) {
13992                 return false;
13993         }
13994
13995         TALLOC_FREE(cache);
13996
13997         /* GETWD_CACHE TESTS */
13998         str1 = talloc_strdup(mem_ctx, "string1");
13999         if (str1 == NULL) {
14000                 return false;
14001         }
14002         ptr2 = str1; /* Keep an alias for comparison. */
14003
14004         str2 = talloc_strdup(mem_ctx, "string2");
14005         if (str2 == NULL) {
14006                 return false;
14007         }
14008
14009         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14010         if (cache == NULL) {
14011                 printf("memcache_init failed\n");
14012                 return false;
14013         }
14014
14015         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14016         /* str1 == NULL now. */
14017         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14018         if (ptr1 == NULL) {
14019                 printf("could not find k2\n");
14020                 return false;
14021         }
14022         if (ptr1 != ptr2) {
14023                 printf("fetch of k2 got wrong string\n");
14024                 return false;
14025         }
14026
14027         /* Add a blob to ensure k2 gets purged. */
14028         d3 = data_blob_talloc_zero(mem_ctx, 180);
14029         memcache_add(cache, STAT_CACHE, k3, d3);
14030
14031         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14032         if (ptr2 != NULL) {
14033                 printf("Did find k2, should have been purged\n");
14034                 return false;
14035         }
14036
14037         /*
14038          * Test that talloc size also is accounted in memcache and
14039          * causes purge of other object.
14040          */
14041
14042         str1 = talloc_zero_size(mem_ctx, 100);
14043         str2 = talloc_zero_size(mem_ctx, 100);
14044
14045         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14046         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14047
14048         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14049         if (ptr3 != NULL) {
14050                 printf("Did find k4, should have been purged\n");
14051                 return false;
14052         }
14053
14054         /*
14055          * Test that adding a duplicate non-talloced
14056          * key/value on top of a talloced key/value takes account
14057          * of the talloc_freed value size.
14058          */
14059         TALLOC_FREE(cache);
14060         TALLOC_FREE(mem_ctx);
14061
14062         mem_ctx = talloc_init("key_replace");
14063         if (mem_ctx == NULL) {
14064                 return false;
14065         }
14066
14067         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14068         if (cache == NULL) {
14069                 return false;
14070         }
14071
14072         /*
14073          * Add a 100 byte talloced string. This will
14074          * store a (4 or 8 byte) pointer and record the
14075          * total talloced size.
14076          */
14077         str1 = talloc_zero_size(mem_ctx, 100);
14078         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14079         /*
14080          * Now overwrite with a small talloced
14081          * value. This should fit in the existing size
14082          * and the total talloced size should be removed
14083          * from the cache size.
14084          */
14085         str1 = talloc_zero_size(mem_ctx, 2);
14086         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14087         /*
14088          * Now store a 20 byte string. If the
14089          * total talloced size wasn't accounted for
14090          * and removed in the overwrite, then this
14091          * will evict k4.
14092          */
14093         str2 = talloc_zero_size(mem_ctx, 20);
14094         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14095
14096         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14097         if (ptr3 == NULL) {
14098                 printf("Did not find k4, should not have been purged\n");
14099                 return false;
14100         }
14101
14102         TALLOC_FREE(cache);
14103         TALLOC_FREE(mem_ctx);
14104
14105         mem_ctx = talloc_init("foo");
14106         if (mem_ctx == NULL) {
14107                 return false;
14108         }
14109
14110         cache = memcache_init(NULL, 0);
14111         if (cache == NULL) {
14112                 return false;
14113         }
14114
14115         str1 = talloc_strdup(mem_ctx, "string1");
14116         if (str1 == NULL) {
14117                 return false;
14118         }
14119         str2 = talloc_strdup(mem_ctx, "string2");
14120         if (str2 == NULL) {
14121                 return false;
14122         }
14123         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14124                             data_blob_string_const("torture"), &str1);
14125         size1 = talloc_total_size(cache);
14126
14127         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14128                             data_blob_string_const("torture"), &str2);
14129         size2 = talloc_total_size(cache);
14130
14131         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14132
14133         if (size2 > size1) {
14134                 printf("memcache leaks memory!\n");
14135                 goto fail;
14136         }
14137
14138         ret = true;
14139  fail:
14140         TALLOC_FREE(cache);
14141         return ret;
14142 }
14143
14144 static void wbclient_done(struct tevent_req *req)
14145 {
14146         wbcErr wbc_err;
14147         struct winbindd_response *wb_resp;
14148         int *i = (int *)tevent_req_callback_data_void(req);
14149
14150         wbc_err = wb_trans_recv(req, req, &wb_resp);
14151         TALLOC_FREE(req);
14152         *i += 1;
14153         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14154 }
14155
14156 static bool run_wbclient_multi_ping(int dummy)
14157 {
14158         struct tevent_context *ev;
14159         struct wb_context **wb_ctx;
14160         struct winbindd_request wb_req;
14161         bool result = false;
14162         int i, j;
14163
14164         BlockSignals(True, SIGPIPE);
14165
14166         ev = tevent_context_init(talloc_tos());
14167         if (ev == NULL) {
14168                 goto fail;
14169         }
14170
14171         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14172         if (wb_ctx == NULL) {
14173                 goto fail;
14174         }
14175
14176         ZERO_STRUCT(wb_req);
14177         wb_req.cmd = WINBINDD_PING;
14178
14179         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14180
14181         for (i=0; i<torture_nprocs; i++) {
14182                 wb_ctx[i] = wb_context_init(ev, NULL);
14183                 if (wb_ctx[i] == NULL) {
14184                         goto fail;
14185                 }
14186                 for (j=0; j<torture_numops; j++) {
14187                         struct tevent_req *req;
14188                         req = wb_trans_send(ev, ev, wb_ctx[i],
14189                                             (j % 2) == 0, &wb_req);
14190                         if (req == NULL) {
14191                                 goto fail;
14192                         }
14193                         tevent_req_set_callback(req, wbclient_done, &i);
14194                 }
14195         }
14196
14197         i = 0;
14198
14199         while (i < torture_nprocs * torture_numops) {
14200                 tevent_loop_once(ev);
14201         }
14202
14203         result = true;
14204  fail:
14205         TALLOC_FREE(ev);
14206         return result;
14207 }
14208
14209 static bool dbtrans_inc(struct db_context *db)
14210 {
14211         struct db_record *rec;
14212         uint32_t val;
14213         bool ret = false;
14214         NTSTATUS status;
14215         TDB_DATA value;
14216
14217         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14218         if (rec == NULL) {
14219                 printf(__location__ "fetch_lock failed\n");
14220                 return false;
14221         }
14222
14223         value = dbwrap_record_get_value(rec);
14224
14225         if (value.dsize != sizeof(uint32_t)) {
14226                 printf(__location__ "value.dsize = %d\n",
14227                        (int)value.dsize);
14228                 goto fail;
14229         }
14230
14231         memcpy(&val, value.dptr, sizeof(val));
14232         val += 1;
14233
14234         status = dbwrap_record_store(
14235                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14236         if (!NT_STATUS_IS_OK(status)) {
14237                 printf(__location__ "store failed: %s\n",
14238                        nt_errstr(status));
14239                 goto fail;
14240         }
14241
14242         ret = true;
14243 fail:
14244         TALLOC_FREE(rec);
14245         return ret;
14246 }
14247
14248 static bool run_local_dbtrans(int dummy)
14249 {
14250         struct db_context *db;
14251         struct db_record *rec;
14252         NTSTATUS status;
14253         uint32_t initial;
14254         int res;
14255         TDB_DATA value;
14256
14257         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14258                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14259                      DBWRAP_FLAG_NONE);
14260         if (db == NULL) {
14261                 printf("Could not open transtest.db\n");
14262                 return false;
14263         }
14264
14265         res = dbwrap_transaction_start(db);
14266         if (res != 0) {
14267                 printf(__location__ "transaction_start failed\n");
14268                 return false;
14269         }
14270
14271         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14272         if (rec == NULL) {
14273                 printf(__location__ "fetch_lock failed\n");
14274                 return false;
14275         }
14276
14277         value = dbwrap_record_get_value(rec);
14278
14279         if (value.dptr == NULL) {
14280                 initial = 0;
14281                 status = dbwrap_record_store(
14282                         rec, make_tdb_data((uint8_t *)&initial,
14283                                            sizeof(initial)),
14284                         0);
14285                 if (!NT_STATUS_IS_OK(status)) {
14286                         printf(__location__ "store returned %s\n",
14287                                nt_errstr(status));
14288                         return false;
14289                 }
14290         }
14291
14292         TALLOC_FREE(rec);
14293
14294         res = dbwrap_transaction_commit(db);
14295         if (res != 0) {
14296                 printf(__location__ "transaction_commit failed\n");
14297                 return false;
14298         }
14299
14300         while (true) {
14301                 uint32_t val, val2;
14302                 int i;
14303
14304                 res = dbwrap_transaction_start(db);
14305                 if (res != 0) {
14306                         printf(__location__ "transaction_start failed\n");
14307                         break;
14308                 }
14309
14310                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14311                 if (!NT_STATUS_IS_OK(status)) {
14312                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14313                                nt_errstr(status));
14314                         break;
14315                 }
14316
14317                 for (i=0; i<10; i++) {
14318                         if (!dbtrans_inc(db)) {
14319                                 return false;
14320                         }
14321                 }
14322
14323                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14324                 if (!NT_STATUS_IS_OK(status)) {
14325                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14326                                nt_errstr(status));
14327                         break;
14328                 }
14329
14330                 if (val2 != val + 10) {
14331                         printf(__location__ "val=%d, val2=%d\n",
14332                                (int)val, (int)val2);
14333                         break;
14334                 }
14335
14336                 printf("val2=%d\r", val2);
14337
14338                 res = dbwrap_transaction_commit(db);
14339                 if (res != 0) {
14340                         printf(__location__ "transaction_commit failed\n");
14341                         break;
14342                 }
14343         }
14344
14345         TALLOC_FREE(db);
14346         return true;
14347 }
14348
14349 /*
14350  * Just a dummy test to be run under a debugger. There's no real way
14351  * to inspect the tevent_poll specific function from outside of
14352  * tevent_poll.c.
14353  */
14354
14355 static bool run_local_tevent_poll(int dummy)
14356 {
14357         struct tevent_context *ev;
14358         struct tevent_fd *fd1, *fd2;
14359         bool result = false;
14360
14361         ev = tevent_context_init_byname(NULL, "poll");
14362         if (ev == NULL) {
14363                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14364                 goto fail;
14365         }
14366
14367         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14368         if (fd1 == NULL) {
14369                 d_fprintf(stderr, "tevent_add_fd failed\n");
14370                 goto fail;
14371         }
14372         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14373         if (fd2 == NULL) {
14374                 d_fprintf(stderr, "tevent_add_fd failed\n");
14375                 goto fail;
14376         }
14377         TALLOC_FREE(fd2);
14378
14379         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14380         if (fd2 == NULL) {
14381                 d_fprintf(stderr, "tevent_add_fd failed\n");
14382                 goto fail;
14383         }
14384
14385         result = true;
14386 fail:
14387         TALLOC_FREE(ev);
14388         return result;
14389 }
14390
14391 static bool run_local_hex_encode_buf(int dummy)
14392 {
14393         char buf[17];
14394         uint8_t src[8];
14395         size_t i;
14396
14397         for (i=0; i<sizeof(src); i++) {
14398                 src[i] = i;
14399         }
14400         hex_encode_buf(buf, src, sizeof(src));
14401         if (strcmp(buf, "0001020304050607") != 0) {
14402                 return false;
14403         }
14404         hex_encode_buf(buf, NULL, 0);
14405         if (buf[0] != '\0') {
14406                 return false;
14407         }
14408         return true;
14409 }
14410
14411 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14412         "0.0.0.0",
14413         "::0",
14414         "1.2.3.1",
14415         "0.0.0.0",
14416         "0.0.0.0",
14417         "1.2.3.2",
14418         "1.2.3.3",
14419         "1.2.3.4",
14420         "1.2.3.5",
14421         "::0",
14422         "1.2.3.6",
14423         "1.2.3.7",
14424         "::0",
14425         "::0",
14426         "::0",
14427         "1.2.3.8",
14428         "1.2.3.9",
14429         "1.2.3.10",
14430         "1.2.3.11",
14431         "1.2.3.12",
14432         "1.2.3.13",
14433         "1001:1111:1111:1000:0:1111:1111:1111",
14434         "1.2.3.1",
14435         "1.2.3.2",
14436         "1.2.3.3",
14437         "1.2.3.12",
14438         "::0",
14439         "::0"
14440 };
14441
14442 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14443         "1.2.3.1",
14444         "1.2.3.2",
14445         "1.2.3.3",
14446         "1.2.3.4",
14447         "1.2.3.5",
14448         "1.2.3.6",
14449         "1.2.3.7",
14450         "1.2.3.8",
14451         "1.2.3.9",
14452         "1.2.3.10",
14453         "1.2.3.11",
14454         "1.2.3.12",
14455         "1.2.3.13",
14456         "1001:1111:1111:1000:0:1111:1111:1111"
14457 };
14458
14459 static bool run_local_remove_duplicate_addrs2(int dummy)
14460 {
14461         struct samba_sockaddr test_vector[28];
14462         size_t count, i;
14463
14464         /* Construct the sockaddr_storage test vector. */
14465         for (i = 0; i < 28; i++) {
14466                 struct addrinfo hints;
14467                 struct addrinfo *res = NULL;
14468                 int ret;
14469
14470                 memset(&hints, '\0', sizeof(hints));
14471                 hints.ai_flags = AI_NUMERICHOST;
14472                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14473                                 NULL,
14474                                 &hints,
14475                                 &res);
14476                 if (ret) {
14477                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14478                                 remove_duplicate_addrs2_test_strings_vector[i]);
14479                         return false;
14480                 }
14481                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14482                 memcpy(&test_vector[i].u.ss,
14483                         res->ai_addr,
14484                         res->ai_addrlen);
14485                 freeaddrinfo(res);
14486         }
14487
14488         count = remove_duplicate_addrs2(test_vector, i);
14489
14490         if (count != 14) {
14491                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14492                         count);
14493                 return false;
14494         }
14495
14496         for (i = 0; i < count; i++) {
14497                 char addr[INET6_ADDRSTRLEN];
14498
14499                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14500
14501                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14502                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14503                                 i,
14504                                 addr,
14505                                 remove_duplicate_addrs2_test_strings_result[i]);
14506                         return false;
14507                 }
14508         }
14509
14510         printf("run_local_remove_duplicate_addrs2: success\n");
14511         return true;
14512 }
14513
14514 static bool run_local_tdb_opener(int dummy)
14515 {
14516         TDB_CONTEXT *t;
14517         unsigned v = 0;
14518
14519         while (1) {
14520                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14521                              O_RDWR|O_CREAT, 0755);
14522                 if (t == NULL) {
14523                         perror("tdb_open failed");
14524                         return false;
14525                 }
14526                 tdb_close(t);
14527
14528                 v += 1;
14529                 printf("\r%u", v);
14530         }
14531         return true;
14532 }
14533
14534 static bool run_local_tdb_writer(int dummy)
14535 {
14536         TDB_CONTEXT *t;
14537         unsigned v = 0;
14538         TDB_DATA val;
14539
14540         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14541         if (t == 0) {
14542                 perror("tdb_open failed");
14543                 return 1;
14544         }
14545
14546         val.dptr = (uint8_t *)&v;
14547         val.dsize = sizeof(v);
14548
14549         while (1) {
14550                 TDB_DATA data;
14551                 int ret;
14552
14553                 ret = tdb_store(t, val, val, 0);
14554                 if (ret != 0) {
14555                         printf("%s\n", tdb_errorstr(t));
14556                 }
14557                 v += 1;
14558                 printf("\r%u", v);
14559
14560                 data = tdb_fetch(t, val);
14561                 if (data.dptr != NULL) {
14562                         SAFE_FREE(data.dptr);
14563                 }
14564         }
14565         return true;
14566 }
14567
14568 static bool run_local_canonicalize_path(int dummy)
14569 {
14570         const char *src[] = {
14571                         "/foo/..",
14572                         "/..",
14573                         "/foo/bar/../baz",
14574                         "/foo/././",
14575                         "/../foo",
14576                         ".././././",
14577                         ".././././../../../boo",
14578                         "./..",
14579                         "/",
14580                         "/../../",
14581                         "/foo/../",
14582                         "/./././",
14583                         "/./././.",
14584                         "/.../././.",
14585                         "/./././.foo",
14586                         "/./././.foo.",
14587                         "/./././foo.",
14588                         "/foo/bar/..",
14589                         "/foo/bar/../baz/",
14590                         "////////////////",
14591                         "/////////./././././.",
14592                         "/./.././../.boo/../baz",
14593                         "/a/component/path",
14594                         "/a/component/path/",
14595                         "/a/component/path/..",
14596                         "/a/component/../path/",
14597                         "///a/./././///component/../////path/",
14598                         NULL
14599                         };
14600         const char *dst[] = {
14601                         "/",
14602                         "/",
14603                         "/foo/baz",
14604                         "/foo",
14605                         "/foo",
14606                         "/",
14607                         "/boo",
14608                         "/",
14609                         "/",
14610                         "/",
14611                         "/",
14612                         "/",
14613                         "/",
14614                         "/...",
14615                         "/.foo",
14616                         "/.foo.",
14617                         "/foo.",
14618                         "/foo",
14619                         "/foo/baz",
14620                         "/",
14621                         "/",
14622                         "/baz",
14623                         "/a/component/path",
14624                         "/a/component/path",
14625                         "/a/component",
14626                         "/a/path",
14627                         "/a/path",
14628                         NULL
14629                         };
14630         unsigned int i;
14631
14632         for (i = 0; src[i] != NULL; i++) {
14633                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14634                 if (d == NULL) {
14635                         perror("talloc fail\n");
14636                         return false;
14637                 }
14638                 if (strcmp(d, dst[i]) != 0) {
14639                         d_fprintf(stderr,
14640                                 "canonicalize mismatch %s -> %s != %s",
14641                                 src[i], d, dst[i]);
14642                         return false;
14643                 }
14644                 talloc_free(d);
14645         }
14646         return true;
14647 }
14648
14649 static bool run_ign_bad_negprot(int dummy)
14650 {
14651         struct tevent_context *ev;
14652         struct tevent_req *req;
14653         struct smbXcli_conn *conn;
14654         struct sockaddr_storage ss;
14655         NTSTATUS status;
14656         int fd;
14657         bool ok;
14658
14659         printf("starting ignore bad negprot\n");
14660
14661         ok = resolve_name(host, &ss, 0x20, true);
14662         if (!ok) {
14663                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14664                 return false;
14665         }
14666
14667         status = open_socket_out(&ss, 445, 10000, &fd);
14668         if (!NT_STATUS_IS_OK(status)) {
14669                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14670                           nt_errstr(status));
14671                 return false;
14672         }
14673
14674         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14675                                    NULL, 0, NULL);
14676         if (conn == NULL) {
14677                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14678                 return false;
14679         }
14680
14681         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14682         if (NT_STATUS_IS_OK(status)) {
14683                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14684                 return false;
14685         }
14686
14687         ev = samba_tevent_context_init(talloc_tos());
14688         if (ev == NULL) {
14689                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14690                 return false;
14691         }
14692
14693         req = smb1cli_session_setup_nt1_send(
14694                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14695                 data_blob_null, data_blob_null, 0x40,
14696                 "Windows 2000 2195", "Windows 2000 5.0");
14697         if (req == NULL) {
14698                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14699                 return false;
14700         }
14701
14702         ok = tevent_req_poll_ntstatus(req, ev, &status);
14703         if (!ok) {
14704                 d_fprintf(stderr, "tevent_req_poll failed\n");
14705                 return false;
14706         }
14707
14708         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14709                                                 NULL, NULL);
14710         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14711                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14712                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14713                           nt_errstr(status));
14714                 return false;
14715         }
14716
14717         TALLOC_FREE(conn);
14718
14719         printf("starting ignore bad negprot\n");
14720
14721         return true;
14722 }
14723
14724 static double create_procs(bool (*fn)(int), bool *result)
14725 {
14726         int i, status;
14727         volatile pid_t *child_status;
14728         volatile bool *child_status_out;
14729         int synccount;
14730         int tries = 8;
14731         struct timeval start;
14732
14733         synccount = 0;
14734
14735         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14736         if (!child_status) {
14737                 printf("Failed to setup shared memory\n");
14738                 return -1;
14739         }
14740
14741         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14742         if (!child_status_out) {
14743                 printf("Failed to setup result status shared memory\n");
14744                 return -1;
14745         }
14746
14747         for (i = 0; i < torture_nprocs; i++) {
14748                 child_status[i] = 0;
14749                 child_status_out[i] = True;
14750         }
14751
14752         start = timeval_current();
14753
14754         for (i=0;i<torture_nprocs;i++) {
14755                 procnum = i;
14756                 if (fork() == 0) {
14757                         pid_t mypid = getpid();
14758                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14759
14760                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14761
14762                         while (1) {
14763                                 if (torture_open_connection(&current_cli, i)) break;
14764                                 if (tries-- == 0) {
14765                                         printf("pid %d failed to start\n", (int)getpid());
14766                                         _exit(1);
14767                                 }
14768                                 smb_msleep(10); 
14769                         }
14770
14771                         child_status[i] = getpid();
14772
14773                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14774
14775                         child_status_out[i] = fn(i);
14776                         _exit(0);
14777                 }
14778         }
14779
14780         do {
14781                 synccount = 0;
14782                 for (i=0;i<torture_nprocs;i++) {
14783                         if (child_status[i]) synccount++;
14784                 }
14785                 if (synccount == torture_nprocs) break;
14786                 smb_msleep(10);
14787         } while (timeval_elapsed(&start) < 30);
14788
14789         if (synccount != torture_nprocs) {
14790                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14791                 *result = False;
14792                 return timeval_elapsed(&start);
14793         }
14794
14795         /* start the client load */
14796         start = timeval_current();
14797
14798         for (i=0;i<torture_nprocs;i++) {
14799                 child_status[i] = 0;
14800         }
14801
14802         printf("%d clients started\n", torture_nprocs);
14803
14804         for (i=0;i<torture_nprocs;i++) {
14805                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14806         }
14807
14808         printf("\n");
14809
14810         for (i=0;i<torture_nprocs;i++) {
14811                 if (!child_status_out[i]) {
14812                         *result = False;
14813                 }
14814         }
14815         return timeval_elapsed(&start);
14816 }
14817
14818 #define FLAG_MULTIPROC 1
14819
14820 static struct {
14821         const char *name;
14822         bool (*fn)(int);
14823         unsigned flags;
14824 } torture_ops[] = {
14825         {
14826                 .name = "FDPASS",
14827                 .fn   = run_fdpasstest,
14828         },
14829         {
14830                 .name = "LOCK1",
14831                 .fn   = run_locktest1,
14832         },
14833         {
14834                 .name = "LOCK2",
14835                 .fn   =  run_locktest2,
14836         },
14837         {
14838                 .name = "LOCK3",
14839                 .fn   =  run_locktest3,
14840         },
14841         {
14842                 .name = "LOCK4",
14843                 .fn   =  run_locktest4,
14844         },
14845         {
14846                 .name = "LOCK5",
14847                 .fn   =  run_locktest5,
14848         },
14849         {
14850                 .name = "LOCK6",
14851                 .fn   =  run_locktest6,
14852         },
14853         {
14854                 .name = "LOCK7",
14855                 .fn   =  run_locktest7,
14856         },
14857         {
14858                 .name = "LOCK8",
14859                 .fn   =  run_locktest8,
14860         },
14861         {
14862                 .name = "LOCK9A",
14863                 .fn   =  run_locktest9a,
14864         },
14865         {
14866                 .name = "LOCK9B",
14867                 .fn   =  run_locktest9b,
14868         },
14869         {
14870                 .name = "LOCK10",
14871                 .fn   =  run_locktest10,
14872         },
14873         {
14874                 .name = "LOCK11",
14875                 .fn   =  run_locktest11,
14876         },
14877         {
14878                 .name = "LOCK12",
14879                 .fn   =  run_locktest12,
14880         },
14881         {
14882                 .name = "LOCK13",
14883                 .fn   =  run_locktest13,
14884         },
14885         {
14886                 .name = "UNLINK",
14887                 .fn   = run_unlinktest,
14888         },
14889         {
14890                 .name = "BROWSE",
14891                 .fn   = run_browsetest,
14892         },
14893         {
14894                 .name = "ATTR",
14895                 .fn   =   run_attrtest,
14896         },
14897         {
14898                 .name = "TRANS2",
14899                 .fn   = run_trans2test,
14900         },
14901         {
14902                 .name  = "MAXFID",
14903                 .fn    = run_maxfidtest,
14904                 .flags = FLAG_MULTIPROC,
14905         },
14906         {
14907                 .name  = "TORTURE",
14908                 .fn    = run_torture,
14909                 .flags = FLAG_MULTIPROC,
14910         },
14911         {
14912                 .name  = "RANDOMIPC",
14913                 .fn    = run_randomipc,
14914         },
14915         {
14916                 .name  = "NEGNOWAIT",
14917                 .fn    = run_negprot_nowait,
14918         },
14919         {
14920                 .name  = "NBENCH",
14921                 .fn    =  run_nbench,
14922         },
14923         {
14924                 .name  = "NBENCH2",
14925                 .fn    = run_nbench2,
14926         },
14927         {
14928                 .name  = "OPLOCK1",
14929                 .fn    =  run_oplock1,
14930         },
14931         {
14932                 .name  = "OPLOCK2",
14933                 .fn    =  run_oplock2,
14934         },
14935         {
14936                 .name  = "OPLOCK4",
14937                 .fn    =  run_oplock4,
14938         },
14939 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14940         {
14941                 .name  = "OPLOCK5",
14942                 .fn    =  run_oplock5,
14943         },
14944 #endif
14945         {
14946                 .name  = "DIR",
14947                 .fn    =  run_dirtest,
14948         },
14949         {
14950                 .name  = "DIR1",
14951                 .fn    =  run_dirtest1,
14952         },
14953         {
14954                 .name  = "DIR-CREATETIME",
14955                 .fn    =  run_dir_createtime,
14956         },
14957         {
14958                 .name  = "DENY1",
14959                 .fn    =  torture_denytest1,
14960         },
14961         {
14962                 .name  = "DENY2",
14963                 .fn    =  torture_denytest2,
14964         },
14965         {
14966                 .name  = "TCON",
14967                 .fn    =  run_tcon_test,
14968         },
14969         {
14970                 .name  = "TCONDEV",
14971                 .fn    =  run_tcon_devtype_test,
14972         },
14973         {
14974                 .name  = "RW1",
14975                 .fn    =  run_readwritetest,
14976         },
14977         {
14978                 .name  = "RW2",
14979                 .fn    =  run_readwritemulti,
14980                 .flags = FLAG_MULTIPROC
14981         },
14982         {
14983                 .name  = "RW3",
14984                 .fn    =  run_readwritelarge,
14985         },
14986         {
14987                 .name  = "RW-SIGNING",
14988                 .fn    =  run_readwritelarge_signtest,
14989         },
14990         {
14991                 .name  = "OPEN",
14992                 .fn    = run_opentest,
14993         },
14994         {
14995                 .name  = "POSIX",
14996                 .fn    = run_simple_posix_open_test,
14997         },
14998         {
14999                 .name  = "POSIX-APPEND",
15000                 .fn    = run_posix_append,
15001         },
15002         {
15003                 .name  = "POSIX-SYMLINK-ACL",
15004                 .fn    = run_acl_symlink_test,
15005         },
15006         {
15007                 .name  = "POSIX-SYMLINK-EA",
15008                 .fn    = run_ea_symlink_test,
15009         },
15010         {
15011                 .name  = "POSIX-STREAM-DELETE",
15012                 .fn    = run_posix_stream_delete,
15013         },
15014         {
15015                 .name  = "POSIX-OFD-LOCK",
15016                 .fn    = run_posix_ofd_lock_test,
15017         },
15018         {
15019                 .name  = "POSIX-BLOCKING-LOCK",
15020                 .fn    = run_posix_blocking_lock,
15021         },
15022         {
15023                 .name  = "POSIX-MKDIR",
15024                 .fn    = run_posix_mkdir_test,
15025         },
15026         {
15027                 .name  = "POSIX-ACL-OPLOCK",
15028                 .fn    = run_posix_acl_oplock_test,
15029         },
15030         {
15031                 .name  = "POSIX-ACL-SHAREROOT",
15032                 .fn    = run_posix_acl_shareroot_test,
15033         },
15034         {
15035                 .name  = "POSIX-LS-WILDCARD",
15036                 .fn    = run_posix_ls_wildcard_test,
15037         },
15038         {
15039                 .name  = "POSIX-LS-SINGLE",
15040                 .fn    = run_posix_ls_single_test,
15041         },
15042         {
15043                 .name  = "POSIX-READLINK",
15044                 .fn    = run_posix_readlink_test,
15045         },
15046         {
15047                 .name  = "POSIX-STAT",
15048                 .fn    = run_posix_stat_test,
15049         },
15050         {
15051                 .name  = "POSIX-SYMLINK-PARENT",
15052                 .fn    = run_posix_symlink_parent_test,
15053         },
15054         {
15055                 .name  = "POSIX-SYMLINK-CHMOD",
15056                 .fn    = run_posix_symlink_chmod_test,
15057         },
15058         {
15059                 .name  = "POSIX-SYMLINK-RENAME",
15060                 .fn    = run_posix_symlink_rename_test,
15061         },
15062         {
15063                 .name  = "POSIX-DIR-DEFAULT-ACL",
15064                 .fn    = run_posix_dir_default_acl_test,
15065         },
15066         {
15067                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15068                 .fn    = run_posix_symlink_getpathinfo_test,
15069         },
15070         {
15071                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15072                 .fn    = run_posix_symlink_setpathinfo_test,
15073         },
15074         {
15075                 .name  = "WINDOWS-BAD-SYMLINK",
15076                 .fn    = run_symlink_open_test,
15077         },
15078         {
15079                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15080                 .fn    = run_smb1_wild_mangle_unlink_test,
15081         },
15082         {
15083                 .name  = "SMB1-WILD-MANGLE-RENAME",
15084                 .fn    = run_smb1_wild_mangle_rename_test,
15085         },
15086         {
15087                 .name  = "CASE-INSENSITIVE-CREATE",
15088                 .fn    = run_case_insensitive_create,
15089         },
15090         {
15091                 .name  = "ASYNC-ECHO",
15092                 .fn    = run_async_echo,
15093         },
15094         {
15095                 .name  = "UID-REGRESSION-TEST",
15096                 .fn    = run_uid_regression_test,
15097         },
15098         {
15099                 .name  = "SHORTNAME-TEST",
15100                 .fn    = run_shortname_test,
15101         },
15102         {
15103                 .name  = "ADDRCHANGE",
15104                 .fn    = run_addrchange,
15105         },
15106 #if 1
15107         {
15108                 .name  = "OPENATTR",
15109                 .fn    = run_openattrtest,
15110         },
15111 #endif
15112         {
15113                 .name  = "XCOPY",
15114                 .fn    = run_xcopy,
15115         },
15116         {
15117                 .name  = "RENAME",
15118                 .fn    = run_rename,
15119         },
15120         {
15121                 .name  = "RENAME-ACCESS",
15122                 .fn    = run_rename_access,
15123         },
15124         {
15125                 .name  = "OWNER-RIGHTS",
15126                 .fn    = run_owner_rights,
15127         },
15128         {
15129                 .name  = "DELETE",
15130                 .fn    = run_deletetest,
15131         },
15132         {
15133                 .name  = "DELETE-STREAM",
15134                 .fn    = run_delete_stream,
15135         },
15136         {
15137                 .name  = "DELETE-PRINT",
15138                 .fn    = run_delete_print_test,
15139         },
15140         {
15141                 .name  = "DELETE-LN",
15142                 .fn    = run_deletetest_ln,
15143         },
15144         {
15145                 .name  = "PROPERTIES",
15146                 .fn    = run_properties,
15147         },
15148         {
15149                 .name  = "MANGLE",
15150                 .fn    = torture_mangle,
15151         },
15152         {
15153                 .name  = "MANGLE1",
15154                 .fn    = run_mangle1,
15155         },
15156         {
15157                 .name  = "MANGLE-ILLEGAL",
15158                 .fn    = run_mangle_illegal,
15159         },
15160         {
15161                 .name  = "W2K",
15162                 .fn    = run_w2ktest,
15163         },
15164         {
15165                 .name  = "TRANS2SCAN",
15166                 .fn    = torture_trans2_scan,
15167         },
15168         {
15169                 .name  = "NTTRANSSCAN",
15170                 .fn    = torture_nttrans_scan,
15171         },
15172         {
15173                 .name  = "UTABLE",
15174                 .fn    = torture_utable,
15175         },
15176         {
15177                 .name  = "CASETABLE",
15178                 .fn    = torture_casetable,
15179         },
15180         {
15181                 .name  = "ERRMAPEXTRACT",
15182                 .fn    = run_error_map_extract,
15183         },
15184         {
15185                 .name  = "PIPE_NUMBER",
15186                 .fn    = run_pipe_number,
15187         },
15188         {
15189                 .name  = "TCON2",
15190                 .fn    =  run_tcon2_test,
15191         },
15192         {
15193                 .name  = "IOCTL",
15194                 .fn    =  torture_ioctl_test,
15195         },
15196         {
15197                 .name  = "CHKPATH",
15198                 .fn    =  torture_chkpath_test,
15199         },
15200         {
15201                 .name  = "FDSESS",
15202                 .fn    = run_fdsesstest,
15203         },
15204         {
15205                 .name  = "EATEST",
15206                 .fn    = run_eatest,
15207         },
15208         {
15209                 .name  = "SESSSETUP_BENCH",
15210                 .fn    = run_sesssetup_bench,
15211         },
15212         {
15213                 .name  = "CHAIN1",
15214                 .fn    = run_chain1,
15215         },
15216         {
15217                 .name  = "CHAIN2",
15218                 .fn    = run_chain2,
15219         },
15220         {
15221                 .name  = "CHAIN3",
15222                 .fn    = run_chain3,
15223         },
15224         {
15225                 .name  = "WINDOWS-WRITE",
15226                 .fn    = run_windows_write,
15227         },
15228         {
15229                 .name  = "LARGE_READX",
15230                 .fn    = run_large_readx,
15231         },
15232         {
15233                 .name  = "MSDFS-ATTRIBUTE",
15234                 .fn    = run_msdfs_attribute,
15235         },
15236         {
15237                 .name  = "NTTRANS-CREATE",
15238                 .fn    = run_nttrans_create,
15239         },
15240         {
15241                 .name  = "NTTRANS-FSCTL",
15242                 .fn    = run_nttrans_fsctl,
15243         },
15244         {
15245                 .name  = "CLI_ECHO",
15246                 .fn    = run_cli_echo,
15247         },
15248         {
15249                 .name  = "CLI_SPLICE",
15250                 .fn    = run_cli_splice,
15251         },
15252         {
15253                 .name  = "TLDAP",
15254                 .fn    = run_tldap,
15255         },
15256         {
15257                 .name  = "STREAMERROR",
15258                 .fn    = run_streamerror,
15259         },
15260         {
15261                 .name  = "NOTIFY-BENCH",
15262                 .fn    = run_notify_bench,
15263         },
15264         {
15265                 .name  = "NOTIFY-BENCH2",
15266                 .fn    = run_notify_bench2,
15267         },
15268         {
15269                 .name  = "NOTIFY-BENCH3",
15270                 .fn    = run_notify_bench3,
15271         },
15272         {
15273                 .name  = "BAD-NBT-SESSION",
15274                 .fn    = run_bad_nbt_session,
15275         },
15276         {
15277                 .name  = "IGN-BAD-NEGPROT",
15278                 .fn    = run_ign_bad_negprot,
15279         },
15280         {
15281                 .name  = "SMB-ANY-CONNECT",
15282                 .fn    = run_smb_any_connect,
15283         },
15284         {
15285                 .name  = "NOTIFY-ONLINE",
15286                 .fn    = run_notify_online,
15287         },
15288         {
15289                 .name  = "SMB2-BASIC",
15290                 .fn    = run_smb2_basic,
15291         },
15292         {
15293                 .name  = "SMB2-NEGPROT",
15294                 .fn    = run_smb2_negprot,
15295         },
15296         {
15297                 .name  = "SMB2-ANONYMOUS",
15298                 .fn    = run_smb2_anonymous,
15299         },
15300         {
15301                 .name  = "SMB2-SESSION-RECONNECT",
15302                 .fn    = run_smb2_session_reconnect,
15303         },
15304         {
15305                 .name  = "SMB2-TCON-DEPENDENCE",
15306                 .fn    = run_smb2_tcon_dependence,
15307         },
15308         {
15309                 .name  = "SMB2-MULTI-CHANNEL",
15310                 .fn    = run_smb2_multi_channel,
15311         },
15312         {
15313                 .name  = "SMB2-SESSION-REAUTH",
15314                 .fn    = run_smb2_session_reauth,
15315         },
15316         {
15317                 .name  = "SMB2-FTRUNCATE",
15318                 .fn    = run_smb2_ftruncate,
15319         },
15320         {
15321                 .name  = "SMB2-DIR-FSYNC",
15322                 .fn    = run_smb2_dir_fsync,
15323         },
15324         {
15325                 .name  = "SMB2-PATH-SLASH",
15326                 .fn    = run_smb2_path_slash,
15327         },
15328         {
15329                 .name  = "SMB1-SYSTEM-SECURITY",
15330                 .fn    = run_smb1_system_security,
15331         },
15332         {
15333                 .name  = "SMB2-SACL",
15334                 .fn    = run_smb2_sacl,
15335         },
15336         {
15337                 .name  = "SMB2-QUOTA1",
15338                 .fn    = run_smb2_quota1,
15339         },
15340         {
15341                 .name  = "SMB2-STREAM-ACL",
15342                 .fn    = run_smb2_stream_acl,
15343         },
15344         {
15345                 .name  = "SMB2-LIST-DIR-ASYNC",
15346                 .fn    = run_list_dir_async_test,
15347         },
15348         {
15349                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15350                 .fn    = run_delete_on_close_non_empty,
15351         },
15352         {
15353                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15354                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15355         },
15356         {
15357                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15358                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15359         },
15360         {
15361                 .name  = "SMB2-DFS-PATHS",
15362                 .fn    = run_smb2_dfs_paths,
15363         },
15364         {
15365                 .name  = "SMB2-NON-DFS-SHARE",
15366                 .fn    = run_smb2_non_dfs_share,
15367         },
15368         {
15369                 .name  = "SMB2-DFS-SHARE-NON-DFS-PATH",
15370                 .fn    = run_smb2_dfs_share_non_dfs_path,
15371         },
15372         {
15373                 .name  = "SMB1-DFS-PATHS",
15374                 .fn    = run_smb1_dfs_paths,
15375         },
15376         {
15377                 .name  = "SMB1-DFS-SEARCH-PATHS",
15378                 .fn    = run_smb1_dfs_search_paths,
15379         },
15380         {
15381                 .name  = "SMB1-DFS-OPERATIONS",
15382                 .fn    = run_smb1_dfs_operations,
15383         },
15384         {
15385                 .name  = "CLEANUP1",
15386                 .fn    = run_cleanup1,
15387         },
15388         {
15389                 .name  = "CLEANUP2",
15390                 .fn    = run_cleanup2,
15391         },
15392         {
15393                 .name  = "CLEANUP4",
15394                 .fn    = run_cleanup4,
15395         },
15396         {
15397                 .name  = "OPLOCK-CANCEL",
15398                 .fn    = run_oplock_cancel,
15399         },
15400         {
15401                 .name  = "PIDHIGH",
15402                 .fn    = run_pidhigh,
15403         },
15404         {
15405                 .name  = "LOCAL-SUBSTITUTE",
15406                 .fn    = run_local_substitute,
15407         },
15408         {
15409                 .name  = "LOCAL-GENCACHE",
15410                 .fn    = run_local_gencache,
15411         },
15412         {
15413                 .name  = "LOCAL-DBWRAP-WATCH1",
15414                 .fn    = run_dbwrap_watch1,
15415         },
15416         {
15417                 .name  = "LOCAL-DBWRAP-WATCH2",
15418                 .fn    = run_dbwrap_watch2,
15419         },
15420         {
15421                 .name  = "LOCAL-DBWRAP-WATCH3",
15422                 .fn    = run_dbwrap_watch3,
15423         },
15424         {
15425                 .name  = "LOCAL-DBWRAP-WATCH4",
15426                 .fn    = run_dbwrap_watch4,
15427         },
15428         {
15429                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
15430                 .fn    = run_dbwrap_do_locked1,
15431         },
15432         {
15433                 .name  = "LOCAL-MESSAGING-READ1",
15434                 .fn    = run_messaging_read1,
15435         },
15436         {
15437                 .name  = "LOCAL-MESSAGING-READ2",
15438                 .fn    = run_messaging_read2,
15439         },
15440         {
15441                 .name  = "LOCAL-MESSAGING-READ3",
15442                 .fn    = run_messaging_read3,
15443         },
15444         {
15445                 .name  = "LOCAL-MESSAGING-READ4",
15446                 .fn    = run_messaging_read4,
15447         },
15448         {
15449                 .name  = "LOCAL-MESSAGING-FDPASS1",
15450                 .fn    = run_messaging_fdpass1,
15451         },
15452         {
15453                 .name  = "LOCAL-MESSAGING-FDPASS2",
15454                 .fn    = run_messaging_fdpass2,
15455         },
15456         {
15457                 .name  = "LOCAL-MESSAGING-FDPASS2a",
15458                 .fn    = run_messaging_fdpass2a,
15459         },
15460         {
15461                 .name  = "LOCAL-MESSAGING-FDPASS2b",
15462                 .fn    = run_messaging_fdpass2b,
15463         },
15464         {
15465                 .name  = "LOCAL-MESSAGING-SEND-ALL",
15466                 .fn    = run_messaging_send_all,
15467         },
15468         {
15469                 .name  = "LOCAL-BASE64",
15470                 .fn    = run_local_base64,
15471         },
15472         {
15473                 .name  = "LOCAL-RBTREE",
15474                 .fn    = run_local_rbtree,
15475         },
15476         {
15477                 .name  = "LOCAL-MEMCACHE",
15478                 .fn    = run_local_memcache,
15479         },
15480         {
15481                 .name  = "LOCAL-STREAM-NAME",
15482                 .fn    = run_local_stream_name,
15483         },
15484         {
15485                 .name  = "LOCAL-STR-MATCH-MSWILD",
15486                 .fn    = run_str_match_mswild,
15487         },
15488         {
15489                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
15490                 .fn    = run_str_match_regex_sub1,
15491         },
15492         {
15493                 .name  = "WBCLIENT-MULTI-PING",
15494                 .fn    = run_wbclient_multi_ping,
15495         },
15496         {
15497                 .name  = "LOCAL-string_to_sid",
15498                 .fn    = run_local_string_to_sid,
15499         },
15500         {
15501                 .name  = "LOCAL-sid_to_string",
15502                 .fn    = run_local_sid_to_string,
15503         },
15504         {
15505                 .name  = "LOCAL-binary_to_sid",
15506                 .fn    = run_local_binary_to_sid,
15507         },
15508         {
15509                 .name  = "LOCAL-DBTRANS",
15510                 .fn    = run_local_dbtrans,
15511         },
15512         {
15513                 .name  = "LOCAL-TEVENT-POLL",
15514                 .fn    = run_local_tevent_poll,
15515         },
15516         {
15517                 .name  = "LOCAL-CONVERT-STRING",
15518                 .fn    = run_local_convert_string,
15519         },
15520         {
15521                 .name  = "LOCAL-CONV-AUTH-INFO",
15522                 .fn    = run_local_conv_auth_info,
15523         },
15524         {
15525                 .name  = "LOCAL-hex_encode_buf",
15526                 .fn    = run_local_hex_encode_buf,
15527         },
15528         {
15529                 .name  = "LOCAL-IDMAP-TDB-COMMON",
15530                 .fn    = run_idmap_tdb_common_test,
15531         },
15532         {
15533                 .name  = "LOCAL-remove_duplicate_addrs2",
15534                 .fn    = run_local_remove_duplicate_addrs2,
15535         },
15536         {
15537                 .name  = "local-tdb-opener",
15538                 .fn    = run_local_tdb_opener,
15539         },
15540         {
15541                 .name  = "local-tdb-writer",
15542                 .fn    = run_local_tdb_writer,
15543         },
15544         {
15545                 .name  = "LOCAL-DBWRAP-CTDB1",
15546                 .fn    = run_local_dbwrap_ctdb1,
15547         },
15548         {
15549                 .name  = "LOCAL-BENCH-PTHREADPOOL",
15550                 .fn    = run_bench_pthreadpool,
15551         },
15552         {
15553                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
15554                 .fn    = run_pthreadpool_tevent,
15555         },
15556         {
15557                 .name  = "LOCAL-G-LOCK1",
15558                 .fn    = run_g_lock1,
15559         },
15560         {
15561                 .name  = "LOCAL-G-LOCK2",
15562                 .fn    = run_g_lock2,
15563         },
15564         {
15565                 .name  = "LOCAL-G-LOCK3",
15566                 .fn    = run_g_lock3,
15567         },
15568         {
15569                 .name  = "LOCAL-G-LOCK4",
15570                 .fn    = run_g_lock4,
15571         },
15572         {
15573                 .name  = "LOCAL-G-LOCK4A",
15574                 .fn    = run_g_lock4a,
15575         },
15576         {
15577                 .name  = "LOCAL-G-LOCK5",
15578                 .fn    = run_g_lock5,
15579         },
15580         {
15581                 .name  = "LOCAL-G-LOCK6",
15582                 .fn    = run_g_lock6,
15583         },
15584         {
15585                 .name  = "LOCAL-G-LOCK7",
15586                 .fn    = run_g_lock7,
15587         },
15588         {
15589                 .name  = "LOCAL-G-LOCK8",
15590                 .fn    = run_g_lock8,
15591         },
15592         {
15593                 .name  = "LOCAL-G-LOCK-PING-PONG",
15594                 .fn    = run_g_lock_ping_pong,
15595         },
15596         {
15597                 .name  = "LOCAL-CANONICALIZE-PATH",
15598                 .fn    = run_local_canonicalize_path,
15599         },
15600         {
15601                 .name  = "LOCAL-NAMEMAP-CACHE1",
15602                 .fn    = run_local_namemap_cache1,
15603         },
15604         {
15605                 .name  = "LOCAL-IDMAP-CACHE1",
15606                 .fn    = run_local_idmap_cache1,
15607         },
15608         {
15609                 .name  = "qpathinfo-bufsize",
15610                 .fn    = run_qpathinfo_bufsize,
15611         },
15612         {
15613                 .name  = "hide-new-files-timeout",
15614                 .fn    = run_hidenewfiles,
15615         },
15616         {
15617                 .name  = "hide-new-files-timeout-showdirs",
15618                 .fn    = run_hidenewfiles_showdirs,
15619         },
15620 #ifdef CLUSTER_SUPPORT
15621         {
15622                 .name  = "ctdbd-conn1",
15623                 .fn    = run_ctdbd_conn1,
15624         },
15625 #endif
15626         {
15627                 .name  = "readdir-timestamp",
15628                 .fn    = run_readdir_timestamp,
15629         },
15630         {
15631                 .name = NULL,
15632         },
15633 };
15634
15635 /****************************************************************************
15636 run a specified test or "ALL"
15637 ****************************************************************************/
15638 static bool run_test(const char *name)
15639 {
15640         bool ret = True;
15641         bool result = True;
15642         bool found = False;
15643         int i;
15644         double t;
15645         if (strequal(name,"ALL")) {
15646                 for (i=0;torture_ops[i].name;i++) {
15647                         run_test(torture_ops[i].name);
15648                 }
15649                 found = True;
15650         }
15651
15652         for (i=0;torture_ops[i].name;i++) {
15653                 fstr_sprintf(randomfname, "\\XX%x", 
15654                          (unsigned)random());
15655
15656                 if (strequal(name, torture_ops[i].name)) {
15657                         found = True;
15658                         printf("Running %s\n", name);
15659                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
15660                                 t = create_procs(torture_ops[i].fn, &result);
15661                                 if (!result) { 
15662                                         ret = False;
15663                                         printf("TEST %s FAILED!\n", name);
15664                                 }
15665                         } else {
15666                                 struct timeval start;
15667                                 start = timeval_current();
15668                                 if (!torture_ops[i].fn(0)) {
15669                                         ret = False;
15670                                         printf("TEST %s FAILED!\n", name);
15671                                 }
15672                                 t = timeval_elapsed(&start);
15673                         }
15674                         printf("%s took %g secs\n\n", name, t);
15675                 }
15676         }
15677
15678         if (!found) {
15679                 printf("Did not find a test named %s\n", name);
15680                 ret = False;
15681         }
15682
15683         return ret;
15684 }
15685
15686
15687 static void usage(void)
15688 {
15689         int i;
15690
15691         printf("WARNING samba4 test suite is much more complete nowadays.\n");
15692         printf("Please use samba4 torture.\n\n");
15693
15694         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15695
15696         printf("\t-d debuglevel\n");
15697         printf("\t-U user%%pass\n");
15698         printf("\t-k                    use kerberos\n");
15699         printf("\t-N numprocs\n");
15700         printf("\t-n my_netbios_name\n");
15701         printf("\t-W workgroup\n");
15702         printf("\t-o num_operations\n");
15703         printf("\t-O socket_options\n");
15704         printf("\t-m maximum protocol\n");
15705         printf("\t-L use oplocks\n");
15706         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
15707         printf("\t-A showall\n");
15708         printf("\t-p port\n");
15709         printf("\t-s seed\n");
15710         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
15711         printf("\t-f filename           filename to test\n");
15712         printf("\t-e                    encrypt\n");
15713         printf("\n\n");
15714
15715         printf("tests are:");
15716         for (i=0;torture_ops[i].name;i++) {
15717                 printf(" %s", torture_ops[i].name);
15718         }
15719         printf("\n");
15720
15721         printf("default test is ALL\n");
15722
15723         exit(1);
15724 }
15725
15726 /****************************************************************************
15727   main program
15728 ****************************************************************************/
15729  int main(int argc,char *argv[])
15730 {
15731         int opt, i;
15732         char *p;
15733         int gotuser = 0;
15734         int gotpass = 0;
15735         bool correct = True;
15736         TALLOC_CTX *frame = talloc_stackframe();
15737         int seed = time(NULL);
15738
15739 #ifdef HAVE_SETBUFFER
15740         setbuffer(stdout, NULL, 0);
15741 #endif
15742
15743         setup_logging("smbtorture", DEBUG_STDOUT);
15744
15745         smb_init_locale();
15746         fault_setup();
15747
15748         if (is_default_dyn_CONFIGFILE()) {
15749                 if(getenv("SMB_CONF_PATH")) {
15750                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15751                 }
15752         }
15753         lp_load_global(get_dyn_CONFIGFILE());
15754         load_interfaces();
15755
15756         if (argc < 2) {
15757                 usage();
15758         }
15759
15760         for(p = argv[1]; *p; p++)
15761           if(*p == '\\')
15762             *p = '/';
15763
15764         if (strncmp(argv[1], "//", 2)) {
15765                 usage();
15766         }
15767
15768         fstrcpy(host, &argv[1][2]);
15769         p = strchr_m(&host[2],'/');
15770         if (!p) {
15771                 usage();
15772         }
15773         *p = 0;
15774         fstrcpy(share, p+1);
15775
15776         fstrcpy(myname, get_myname(talloc_tos()));
15777         if (!*myname) {
15778                 fprintf(stderr, "Failed to get my hostname.\n");
15779                 return 1;
15780         }
15781
15782         if (*username == 0 && getenv("LOGNAME")) {
15783           fstrcpy(username,getenv("LOGNAME"));
15784         }
15785
15786         argc--;
15787         argv++;
15788
15789         fstrcpy(workgroup, lp_workgroup());
15790
15791         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15792                != EOF) {
15793                 switch (opt) {
15794                 case 'p':
15795                         port_to_use = atoi(optarg);
15796                         break;
15797                 case 's':
15798                         seed = atoi(optarg);
15799                         break;
15800                 case 'W':
15801                         fstrcpy(workgroup,optarg);
15802                         break;
15803                 case 'm':
15804                         lp_set_cmdline("client max protocol", optarg);
15805                         break;
15806                 case 'N':
15807                         torture_nprocs = atoi(optarg);
15808                         break;
15809                 case 'o':
15810                         torture_numops = atoi(optarg);
15811                         break;
15812                 case 'd':
15813                         lp_set_cmdline("log level", optarg);
15814                         break;
15815                 case 'O':
15816                         sockops = optarg;
15817                         break;
15818                 case 'L':
15819                         use_oplocks = True;
15820                         break;
15821                 case 'l':
15822                         local_path = optarg;
15823                         break;
15824                 case 'A':
15825                         torture_showall = True;
15826                         break;
15827                 case 'n':
15828                         fstrcpy(myname, optarg);
15829                         break;
15830                 case 'c':
15831                         client_txt = optarg;
15832                         break;
15833                 case 'e':
15834                         do_encrypt = true;
15835                         break;
15836                 case 'k':
15837 #ifdef HAVE_KRB5
15838                         use_kerberos = True;
15839 #else
15840                         d_printf("No kerberos support compiled in\n");
15841                         exit(1);
15842 #endif
15843                         break;
15844                 case 'U':
15845                         gotuser = 1;
15846                         fstrcpy(username,optarg);
15847                         p = strchr_m(username,'%');
15848                         if (p) {
15849                                 *p = 0;
15850                                 fstrcpy(password, p+1);
15851                                 gotpass = 1;
15852                         }
15853                         break;
15854                 case 'b':
15855                         fstrcpy(multishare_conn_fname, optarg);
15856                         use_multishare_conn = True;
15857                         break;
15858                 case 'B':
15859                         torture_blocksize = atoi(optarg);
15860                         break;
15861                 case 'f':
15862                         test_filename = SMB_STRDUP(optarg);
15863                         break;
15864                 default:
15865                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15866                         usage();
15867                 }
15868         }
15869
15870         d_printf("using seed %d\n", seed);
15871
15872         srandom(seed);
15873
15874         if(use_kerberos && !gotuser) gotpass = True;
15875
15876         while (!gotpass) {
15877                 char pwd[256] = {0};
15878                 int rc;
15879
15880                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15881                 if (rc == 0) {
15882                         fstrcpy(password, pwd);
15883                         gotpass = 1;
15884                 }
15885         }
15886
15887         printf("host=%s share=%s user=%s myname=%s\n", 
15888                host, share, username, myname);
15889
15890         torture_creds = cli_session_creds_init(frame,
15891                                                username,
15892                                                workgroup,
15893                                                NULL, /* realm */
15894                                                password,
15895                                                use_kerberos,
15896                                                false, /* fallback_after_kerberos */
15897                                                false, /* use_ccache */
15898                                                false); /* password_is_nt_hash */
15899         if (torture_creds == NULL) {
15900                 d_printf("cli_session_creds_init() failed.\n");
15901                 exit(1);
15902         }
15903
15904         if (argc == optind) {
15905                 correct = run_test("ALL");
15906         } else {
15907                 for (i=optind;i<argc;i++) {
15908                         if (!run_test(argv[i])) {
15909                                 correct = False;
15910                         }
15911                 }
15912         }
15913
15914         TALLOC_FREE(frame);
15915
15916         if (correct) {
15917                 return(0);
15918         } else {
15919                 return(1);
15920         }
15921 }