s3: torture: Add 2 new tests SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO, SMB2-DEL-ON-CLOSE...
[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         uint16_t vuid1, vuid2;
1439         char buf[4];
1440         bool ret = True;
1441         NTSTATUS status;
1442
1443         memset(buf, '\0', sizeof(buf));
1444
1445         if (!torture_open_connection(&cli, 0)) {
1446                 return False;
1447         }
1448         smbXcli_conn_set_sockopt(cli->conn, sockops);
1449
1450         printf("starting tcontest\n");
1451
1452         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1453
1454         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1455         if (!NT_STATUS_IS_OK(status)) {
1456                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1457                 return False;
1458         }
1459
1460         cnum1 = cli_state_get_tid(cli);
1461         vuid1 = cli_state_get_uid(cli);
1462
1463         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1464         if (!NT_STATUS_IS_OK(status)) {
1465                 printf("initial write failed (%s)", nt_errstr(status));
1466                 return False;
1467         }
1468
1469         orig_tcon = cli_state_save_tcon(cli);
1470         if (orig_tcon == NULL) {
1471                 return false;
1472         }
1473
1474         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1475         if (!NT_STATUS_IS_OK(status)) {
1476                 printf("%s refused 2nd tree connect (%s)\n", host,
1477                        nt_errstr(status));
1478                 cli_state_restore_tcon(cli, orig_tcon);
1479                 cli_shutdown(cli);
1480                 return False;
1481         }
1482
1483         cnum2 = cli_state_get_tid(cli);
1484         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1485         vuid2 = cli_state_get_uid(cli) + 1;
1486
1487         /* try a write with the wrong tid */
1488         cli_state_set_tid(cli, cnum2);
1489
1490         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1491         if (NT_STATUS_IS_OK(status)) {
1492                 printf("* server allows write with wrong TID\n");
1493                 ret = False;
1494         } else {
1495                 printf("server fails write with wrong TID : %s\n",
1496                        nt_errstr(status));
1497         }
1498
1499
1500         /* try a write with an invalid tid */
1501         cli_state_set_tid(cli, cnum3);
1502
1503         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1504         if (NT_STATUS_IS_OK(status)) {
1505                 printf("* server allows write with invalid TID\n");
1506                 ret = False;
1507         } else {
1508                 printf("server fails write with invalid TID : %s\n",
1509                        nt_errstr(status));
1510         }
1511
1512         /* try a write with an invalid vuid */
1513         cli_state_set_uid(cli, vuid2);
1514         cli_state_set_tid(cli, cnum1);
1515
1516         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1517         if (NT_STATUS_IS_OK(status)) {
1518                 printf("* server allows write with invalid VUID\n");
1519                 ret = False;
1520         } else {
1521                 printf("server fails write with invalid VUID : %s\n",
1522                        nt_errstr(status));
1523         }
1524
1525         cli_state_set_tid(cli, cnum1);
1526         cli_state_set_uid(cli, vuid1);
1527
1528         status = cli_close(cli, fnum1);
1529         if (!NT_STATUS_IS_OK(status)) {
1530                 printf("close failed (%s)\n", nt_errstr(status));
1531                 cli_state_restore_tcon(cli, orig_tcon);
1532                 cli_shutdown(cli);
1533                 return False;
1534         }
1535
1536         cli_state_set_tid(cli, cnum2);
1537
1538         status = cli_tdis(cli);
1539         if (!NT_STATUS_IS_OK(status)) {
1540                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1541                 cli_state_restore_tcon(cli, orig_tcon);
1542                 cli_shutdown(cli);
1543                 return False;
1544         }
1545
1546         cli_state_restore_tcon(cli, orig_tcon);
1547
1548         cli_state_set_tid(cli, cnum1);
1549
1550         if (!torture_close_connection(cli)) {
1551                 return False;
1552         }
1553
1554         return ret;
1555 }
1556
1557
1558 /*
1559  checks for old style tcon support
1560  */
1561 static bool run_tcon2_test(int dummy)
1562 {
1563         static struct cli_state *cli;
1564         uint16_t cnum, max_xmit;
1565         char *service;
1566         NTSTATUS status;
1567
1568         if (!torture_open_connection(&cli, 0)) {
1569                 return False;
1570         }
1571         smbXcli_conn_set_sockopt(cli->conn, sockops);
1572
1573         printf("starting tcon2 test\n");
1574
1575         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1576                 return false;
1577         }
1578
1579         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1580
1581         SAFE_FREE(service);
1582
1583         if (!NT_STATUS_IS_OK(status)) {
1584                 printf("tcon2 failed : %s\n", nt_errstr(status));
1585         } else {
1586                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1587                        (int)max_xmit, (int)cnum);
1588         }
1589
1590         if (!torture_close_connection(cli)) {
1591                 return False;
1592         }
1593
1594         printf("Passed tcon2 test\n");
1595         return True;
1596 }
1597
1598 static bool tcon_devtest(struct cli_state *cli,
1599                          const char *myshare, const char *devtype,
1600                          const char *return_devtype,
1601                          NTSTATUS expected_error)
1602 {
1603         NTSTATUS status;
1604         bool ret;
1605
1606         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1607
1608         if (NT_STATUS_IS_OK(expected_error)) {
1609                 if (NT_STATUS_IS_OK(status)) {
1610                         if (return_devtype != NULL &&
1611                             strequal(cli->dev, return_devtype)) {
1612                                 ret = True;
1613                         } else { 
1614                                 printf("tconX to share %s with type %s "
1615                                        "succeeded but returned the wrong "
1616                                        "device type (got [%s] but should have got [%s])\n",
1617                                        myshare, devtype, cli->dev, return_devtype);
1618                                 ret = False;
1619                         }
1620                 } else {
1621                         printf("tconX to share %s with type %s "
1622                                "should have succeeded but failed\n",
1623                                myshare, devtype);
1624                         ret = False;
1625                 }
1626                 cli_tdis(cli);
1627         } else {
1628                 if (NT_STATUS_IS_OK(status)) {
1629                         printf("tconx to share %s with type %s "
1630                                "should have failed but succeeded\n",
1631                                myshare, devtype);
1632                         ret = False;
1633                 } else {
1634                         if (NT_STATUS_EQUAL(status, expected_error)) {
1635                                 ret = True;
1636                         } else {
1637                                 printf("Returned unexpected error\n");
1638                                 ret = False;
1639                         }
1640                 }
1641         }
1642         return ret;
1643 }
1644
1645 /*
1646  checks for correct tconX support
1647  */
1648 static bool run_tcon_devtype_test(int dummy)
1649 {
1650         static struct cli_state *cli1 = NULL;
1651         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1652         NTSTATUS status;
1653         bool ret = True;
1654
1655         status = cli_full_connection_creds(&cli1,
1656                                            myname,
1657                                            host,
1658                                            NULL, /* dest_ss */
1659                                            port_to_use,
1660                                            NULL, /* service */
1661                                            NULL, /* service_type */
1662                                            torture_creds,
1663                                            flags);
1664
1665         if (!NT_STATUS_IS_OK(status)) {
1666                 printf("could not open connection\n");
1667                 return False;
1668         }
1669
1670         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1671                 ret = False;
1672
1673         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1674                 ret = False;
1675
1676         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1677                 ret = False;
1678
1679         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1680                 ret = False;
1681
1682         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1683                 ret = False;
1684
1685         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1686                 ret = False;
1687
1688         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1689                 ret = False;
1690
1691         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1692                 ret = False;
1693
1694         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1695                 ret = False;
1696
1697         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1698                 ret = False;
1699
1700         cli_shutdown(cli1);
1701
1702         if (ret)
1703                 printf("Passed tcondevtest\n");
1704
1705         return ret;
1706 }
1707
1708
1709 /*
1710   This test checks that 
1711
1712   1) the server supports multiple locking contexts on the one SMB
1713   connection, distinguished by PID.  
1714
1715   2) the server correctly fails overlapping locks made by the same PID (this
1716      goes against POSIX behaviour, which is why it is tricky to implement)
1717
1718   3) the server denies unlock requests by an incorrect client PID
1719 */
1720 static bool run_locktest2(int dummy)
1721 {
1722         static struct cli_state *cli;
1723         const char *fname = "\\lockt2.lck";
1724         uint16_t fnum1, fnum2, fnum3;
1725         bool correct = True;
1726         NTSTATUS status;
1727
1728         if (!torture_open_connection(&cli, 0)) {
1729                 return False;
1730         }
1731
1732         smbXcli_conn_set_sockopt(cli->conn, sockops);
1733
1734         printf("starting locktest2\n");
1735
1736         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1737
1738         cli_setpid(cli, 1);
1739
1740         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1741         if (!NT_STATUS_IS_OK(status)) {
1742                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1743                 return False;
1744         }
1745
1746         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1747         if (!NT_STATUS_IS_OK(status)) {
1748                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1749                 return False;
1750         }
1751
1752         cli_setpid(cli, 2);
1753
1754         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1755         if (!NT_STATUS_IS_OK(status)) {
1756                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1757                 return False;
1758         }
1759
1760         cli_setpid(cli, 1);
1761
1762         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1763         if (!NT_STATUS_IS_OK(status)) {
1764                 printf("lock1 failed (%s)\n", nt_errstr(status));
1765                 return false;
1766         }
1767
1768         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1769         if (NT_STATUS_IS_OK(status)) {
1770                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1771                 correct = false;
1772         } else {
1773                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1774                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1775                         return false;
1776                 }
1777         }
1778
1779         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1780         if (NT_STATUS_IS_OK(status)) {
1781                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1782                 correct = false;
1783         } else {
1784                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1785                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1786                         return false;
1787                 }
1788         }
1789
1790         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1791         if (NT_STATUS_IS_OK(status)) {
1792                 printf("READ lock2 succeeded! This is a locking bug\n");
1793                 correct = false;
1794         } else {
1795                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1796                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1797                         return false;
1798                 }
1799         }
1800
1801         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1802         if (!NT_STATUS_IS_OK(status)) {
1803                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1804         }
1805         cli_setpid(cli, 2);
1806         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1807                 printf("unlock at 100 succeeded! This is a locking bug\n");
1808                 correct = False;
1809         }
1810
1811         status = cli_unlock(cli, fnum1, 0, 4);
1812         if (NT_STATUS_IS_OK(status)) {
1813                 printf("unlock1 succeeded! This is a locking bug\n");
1814                 correct = false;
1815         } else {
1816                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1817                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1818                         return false;
1819                 }
1820         }
1821
1822         status = cli_unlock(cli, fnum1, 0, 8);
1823         if (NT_STATUS_IS_OK(status)) {
1824                 printf("unlock2 succeeded! This is a locking bug\n");
1825                 correct = false;
1826         } else {
1827                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1828                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1829                         return false;
1830                 }
1831         }
1832
1833         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1834         if (NT_STATUS_IS_OK(status)) {
1835                 printf("lock3 succeeded! This is a locking bug\n");
1836                 correct = false;
1837         } else {
1838                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1839                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1840                         return false;
1841                 }
1842         }
1843
1844         cli_setpid(cli, 1);
1845
1846         status = cli_close(cli, fnum1);
1847         if (!NT_STATUS_IS_OK(status)) {
1848                 printf("close1 failed (%s)\n", nt_errstr(status));
1849                 return False;
1850         }
1851
1852         status = cli_close(cli, fnum2);
1853         if (!NT_STATUS_IS_OK(status)) {
1854                 printf("close2 failed (%s)\n", nt_errstr(status));
1855                 return False;
1856         }
1857
1858         status = cli_close(cli, fnum3);
1859         if (!NT_STATUS_IS_OK(status)) {
1860                 printf("close3 failed (%s)\n", nt_errstr(status));
1861                 return False;
1862         }
1863
1864         if (!torture_close_connection(cli)) {
1865                 correct = False;
1866         }
1867
1868         printf("locktest2 finished\n");
1869
1870         return correct;
1871 }
1872
1873
1874 /*
1875   This test checks that 
1876
1877   1) the server supports the full offset range in lock requests
1878 */
1879 static bool run_locktest3(int dummy)
1880 {
1881         static struct cli_state *cli1, *cli2;
1882         const char *fname = "\\lockt3.lck";
1883         uint16_t fnum1, fnum2;
1884         int i;
1885         uint32_t offset;
1886         bool correct = True;
1887         NTSTATUS status;
1888
1889 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1890
1891         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1892                 return False;
1893         }
1894         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1895         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1896
1897         printf("starting locktest3\n");
1898
1899         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1900
1901         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1902                          &fnum1);
1903         if (!NT_STATUS_IS_OK(status)) {
1904                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1905                 return False;
1906         }
1907
1908         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1909         if (!NT_STATUS_IS_OK(status)) {
1910                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1911                 return False;
1912         }
1913
1914         for (offset=i=0;i<torture_numops;i++) {
1915                 NEXT_OFFSET;
1916
1917                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1918                 if (!NT_STATUS_IS_OK(status)) {
1919                         printf("lock1 %d failed (%s)\n", 
1920                                i,
1921                                nt_errstr(status));
1922                         return False;
1923                 }
1924
1925                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1926                 if (!NT_STATUS_IS_OK(status)) {
1927                         printf("lock2 %d failed (%s)\n", 
1928                                i,
1929                                nt_errstr(status));
1930                         return False;
1931                 }
1932         }
1933
1934         for (offset=i=0;i<torture_numops;i++) {
1935                 NEXT_OFFSET;
1936
1937                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1938                 if (NT_STATUS_IS_OK(status)) {
1939                         printf("error: lock1 %d succeeded!\n", i);
1940                         return False;
1941                 }
1942
1943                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1944                 if (NT_STATUS_IS_OK(status)) {
1945                         printf("error: lock2 %d succeeded!\n", i);
1946                         return False;
1947                 }
1948
1949                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1950                 if (NT_STATUS_IS_OK(status)) {
1951                         printf("error: lock3 %d succeeded!\n", i);
1952                         return False;
1953                 }
1954
1955                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1956                 if (NT_STATUS_IS_OK(status)) {
1957                         printf("error: lock4 %d succeeded!\n", i);
1958                         return False;
1959                 }
1960         }
1961
1962         for (offset=i=0;i<torture_numops;i++) {
1963                 NEXT_OFFSET;
1964
1965                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1966                 if (!NT_STATUS_IS_OK(status)) {
1967                         printf("unlock1 %d failed (%s)\n", 
1968                                i,
1969                                nt_errstr(status));
1970                         return False;
1971                 }
1972
1973                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1974                 if (!NT_STATUS_IS_OK(status)) {
1975                         printf("unlock2 %d failed (%s)\n", 
1976                                i,
1977                                nt_errstr(status));
1978                         return False;
1979                 }
1980         }
1981
1982         status = cli_close(cli1, fnum1);
1983         if (!NT_STATUS_IS_OK(status)) {
1984                 printf("close1 failed (%s)\n", nt_errstr(status));
1985                 return False;
1986         }
1987
1988         status = cli_close(cli2, fnum2);
1989         if (!NT_STATUS_IS_OK(status)) {
1990                 printf("close2 failed (%s)\n", nt_errstr(status));
1991                 return False;
1992         }
1993
1994         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1995         if (!NT_STATUS_IS_OK(status)) {
1996                 printf("unlink failed (%s)\n", nt_errstr(status));
1997                 return False;
1998         }
1999
2000         if (!torture_close_connection(cli1)) {
2001                 correct = False;
2002         }
2003
2004         if (!torture_close_connection(cli2)) {
2005                 correct = False;
2006         }
2007
2008         printf("finished locktest3\n");
2009
2010         return correct;
2011 }
2012
2013 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2014                            char *buf, off_t offset, size_t size,
2015                            size_t *nread, size_t expect)
2016 {
2017         NTSTATUS status;
2018         size_t l_nread;
2019
2020         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2021
2022         if(!NT_STATUS_IS_OK(status)) {
2023                 return false;
2024         } else if (l_nread != expect) {
2025                 return false;
2026         }
2027
2028         if (nread) {
2029                 *nread = l_nread;
2030         }
2031
2032         return true;
2033 }
2034
2035 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2036         printf("** "); correct = False; \
2037         }
2038
2039 /*
2040   looks at overlapping locks
2041 */
2042 static bool run_locktest4(int dummy)
2043 {
2044         static struct cli_state *cli1, *cli2;
2045         const char *fname = "\\lockt4.lck";
2046         uint16_t fnum1, fnum2, f;
2047         bool ret;
2048         char buf[1000];
2049         bool correct = True;
2050         NTSTATUS status;
2051
2052         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2053                 return False;
2054         }
2055
2056         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2057         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2058
2059         printf("starting locktest4\n");
2060
2061         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2062
2063         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2064         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2065
2066         memset(buf, 0, sizeof(buf));
2067
2068         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2069                               NULL);
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 printf("Failed to create file: %s\n", nt_errstr(status));
2072                 correct = False;
2073                 goto fail;
2074         }
2075
2076         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2077               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2078         EXPECTED(ret, False);
2079         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2080
2081         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2082               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2083         EXPECTED(ret, True);
2084         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2085
2086         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2087               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2088         EXPECTED(ret, False);
2089         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2090
2091         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2092               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2093         EXPECTED(ret, True);
2094         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2095
2096         ret = (cli_setpid(cli1, 1),
2097               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2098               (cli_setpid(cli1, 2),
2099               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2100         EXPECTED(ret, False);
2101         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2102
2103         ret = (cli_setpid(cli1, 1),
2104               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2105               (cli_setpid(cli1, 2),
2106               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2107         EXPECTED(ret, True);
2108         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2109
2110         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2111               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2112         EXPECTED(ret, True);
2113         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2114
2115         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2116               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2117         EXPECTED(ret, False);
2118         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2119
2120         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2121               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2122         EXPECTED(ret, False);
2123         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2124
2125         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2126               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2127         EXPECTED(ret, True);
2128         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2129
2130         ret = (cli_setpid(cli1, 1),
2131              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2132              (cli_setpid(cli1, 2),
2133              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2134         EXPECTED(ret, False);
2135         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2136
2137         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2138               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2139               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2140         EXPECTED(ret, False);
2141         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2142
2143
2144         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2145               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2146         EXPECTED(ret, False);
2147         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2148
2149         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2150         ret = NT_STATUS_IS_OK(status);
2151         if (ret) {
2152                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2153                                       NULL);
2154                 ret = NT_STATUS_IS_OK(status);
2155         }
2156         EXPECTED(ret, False);
2157         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2158
2159
2160         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2161               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2162               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2163               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2164         EXPECTED(ret, True);
2165         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2166
2167
2168         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2169               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2170               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2171               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2172               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2173                                              150, 4, NULL))) &&
2174               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2175         EXPECTED(ret, True);
2176         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2177
2178         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2179               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2180               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2181                                            160, 4, NULL)) &&
2182               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2183         EXPECTED(ret, True);
2184         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2185
2186         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2187               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2188               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2189                                            170, 4, NULL)) &&
2190               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2191         EXPECTED(ret, True);
2192         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2193
2194         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2195               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2196               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2197               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2198                                             190, 4, NULL)) &&
2199               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2200         EXPECTED(ret, True);
2201         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2202
2203         cli_close(cli1, fnum1);
2204         cli_close(cli2, fnum2);
2205         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2206         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2207         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2208               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2209               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2210               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2211               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2212         cli_close(cli1, f);
2213         cli_close(cli1, fnum1);
2214         EXPECTED(ret, True);
2215         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2216
2217  fail:
2218         cli_close(cli1, fnum1);
2219         cli_close(cli2, fnum2);
2220         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2221         torture_close_connection(cli1);
2222         torture_close_connection(cli2);
2223
2224         printf("finished locktest4\n");
2225         return correct;
2226 }
2227
2228 /*
2229   looks at lock upgrade/downgrade.
2230 */
2231 static bool run_locktest5(int dummy)
2232 {
2233         static struct cli_state *cli1, *cli2;
2234         const char *fname = "\\lockt5.lck";
2235         uint16_t fnum1, fnum2, fnum3;
2236         bool ret;
2237         char buf[1000];
2238         bool correct = True;
2239         NTSTATUS status;
2240
2241         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2242                 return False;
2243         }
2244
2245         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2246         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2247
2248         printf("starting locktest5\n");
2249
2250         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2251
2252         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2253         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2254         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2255
2256         memset(buf, 0, sizeof(buf));
2257
2258         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2259                               NULL);
2260         if (!NT_STATUS_IS_OK(status)) {
2261                 printf("Failed to create file: %s\n", nt_errstr(status));
2262                 correct = False;
2263                 goto fail;
2264         }
2265
2266         /* Check for NT bug... */
2267         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2268               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2269         cli_close(cli1, fnum1);
2270         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2271         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2272         ret = NT_STATUS_IS_OK(status);
2273         EXPECTED(ret, True);
2274         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2275         cli_close(cli1, fnum1);
2276         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2277         cli_unlock(cli1, fnum3, 0, 1);
2278
2279         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2280               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2281         EXPECTED(ret, True);
2282         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2283
2284         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2285         ret = NT_STATUS_IS_OK(status);
2286         EXPECTED(ret, False);
2287
2288         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2289
2290         /* Unlock the process 2 lock. */
2291         cli_unlock(cli2, fnum2, 0, 4);
2292
2293         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2294         ret = NT_STATUS_IS_OK(status);
2295         EXPECTED(ret, False);
2296
2297         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2298
2299         /* Unlock the process 1 fnum3 lock. */
2300         cli_unlock(cli1, fnum3, 0, 4);
2301
2302         /* Stack 2 more locks here. */
2303         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2304               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2305
2306         EXPECTED(ret, True);
2307         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2308
2309         /* Unlock the first process lock, then check this was the WRITE lock that was
2310                 removed. */
2311
2312         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2313               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2314
2315         EXPECTED(ret, True);
2316         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2317
2318         /* Unlock the process 2 lock. */
2319         cli_unlock(cli2, fnum2, 0, 4);
2320
2321         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2322
2323         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2324                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2325                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2326
2327         EXPECTED(ret, True);
2328         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2329
2330         /* Ensure the next unlock fails. */
2331         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2332         EXPECTED(ret, False);
2333         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2334
2335         /* Ensure connection 2 can get a write lock. */
2336         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2337         ret = NT_STATUS_IS_OK(status);
2338         EXPECTED(ret, True);
2339
2340         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2341
2342
2343  fail:
2344         cli_close(cli1, fnum1);
2345         cli_close(cli2, fnum2);
2346         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2347         if (!torture_close_connection(cli1)) {
2348                 correct = False;
2349         }
2350         if (!torture_close_connection(cli2)) {
2351                 correct = False;
2352         }
2353
2354         printf("finished locktest5\n");
2355
2356         return correct;
2357 }
2358
2359 /*
2360   tries the unusual lockingX locktype bits
2361 */
2362 static bool run_locktest6(int dummy)
2363 {
2364         static struct cli_state *cli;
2365         const char *fname[1] = { "\\lock6.txt" };
2366         int i;
2367         uint16_t fnum;
2368         NTSTATUS status;
2369
2370         if (!torture_open_connection(&cli, 0)) {
2371                 return False;
2372         }
2373
2374         smbXcli_conn_set_sockopt(cli->conn, sockops);
2375
2376         printf("starting locktest6\n");
2377
2378         for (i=0;i<1;i++) {
2379                 printf("Testing %s\n", fname[i]);
2380
2381                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2382
2383                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2384                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2385                 cli_close(cli, fnum);
2386                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2387
2388                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2389                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2390                 cli_close(cli, fnum);
2391                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2392
2393                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2394         }
2395
2396         torture_close_connection(cli);
2397
2398         printf("finished locktest6\n");
2399         return True;
2400 }
2401
2402 static bool run_locktest7(int dummy)
2403 {
2404         struct cli_state *cli1;
2405         const char *fname = "\\lockt7.lck";
2406         uint16_t fnum1;
2407         char buf[200];
2408         bool correct = False;
2409         size_t nread;
2410         NTSTATUS status;
2411
2412         if (!torture_open_connection(&cli1, 0)) {
2413                 return False;
2414         }
2415
2416         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2417
2418         printf("starting locktest7\n");
2419
2420         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2421
2422         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2423
2424         memset(buf, 0, sizeof(buf));
2425
2426         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2427                               NULL);
2428         if (!NT_STATUS_IS_OK(status)) {
2429                 printf("Failed to create file: %s\n", nt_errstr(status));
2430                 goto fail;
2431         }
2432
2433         cli_setpid(cli1, 1);
2434
2435         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2436         if (!NT_STATUS_IS_OK(status)) {
2437                 printf("Unable to apply read lock on range 130:4, "
2438                        "error was %s\n", nt_errstr(status));
2439                 goto fail;
2440         } else {
2441                 printf("pid1 successfully locked range 130:4 for READ\n");
2442         }
2443
2444         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2445         if (!NT_STATUS_IS_OK(status)) {
2446                 printf("pid1 unable to read the range 130:4, error was %s\n",
2447                       nt_errstr(status));
2448                 goto fail;
2449         } else if (nread != 4) {
2450                 printf("pid1 unable to read the range 130:4, "
2451                        "recv %ld req %d\n", (unsigned long)nread, 4);
2452                 goto fail;
2453         } else {
2454                 printf("pid1 successfully read the range 130:4\n");
2455         }
2456
2457         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2458         if (!NT_STATUS_IS_OK(status)) {
2459                 printf("pid1 unable to write to the range 130:4, error was "
2460                        "%s\n", nt_errstr(status));
2461                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2462                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2463                         goto fail;
2464                 }
2465         } else {
2466                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2467                 goto fail;
2468         }
2469
2470         cli_setpid(cli1, 2);
2471
2472         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2473         if (!NT_STATUS_IS_OK(status)) {
2474                 printf("pid2 unable to read the range 130:4, error was %s\n",
2475                       nt_errstr(status));
2476                 goto fail;
2477         } else if (nread != 4) {
2478                 printf("pid2 unable to read the range 130:4, "
2479                        "recv %ld req %d\n", (unsigned long)nread, 4);
2480                 goto fail;
2481         } else {
2482                 printf("pid2 successfully read the range 130:4\n");
2483         }
2484
2485         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2486         if (!NT_STATUS_IS_OK(status)) {
2487                 printf("pid2 unable to write to the range 130:4, error was "
2488                        "%s\n", nt_errstr(status));
2489                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2490                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2491                         goto fail;
2492                 }
2493         } else {
2494                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2495                 goto fail;
2496         }
2497
2498         cli_setpid(cli1, 1);
2499         cli_unlock(cli1, fnum1, 130, 4);
2500
2501         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2504                 goto fail;
2505         } else {
2506                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2507         }
2508
2509         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2510         if (!NT_STATUS_IS_OK(status)) {
2511                 printf("pid1 unable to read the range 130:4, error was %s\n",
2512                       nt_errstr(status));
2513                 goto fail;
2514         } else if (nread != 4) {
2515                 printf("pid1 unable to read the range 130:4, "
2516                        "recv %ld req %d\n", (unsigned long)nread, 4);
2517                 goto fail;
2518         } else {
2519                 printf("pid1 successfully read the range 130:4\n");
2520         }
2521
2522         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2523         if (!NT_STATUS_IS_OK(status)) {
2524                 printf("pid1 unable to write to the range 130:4, error was "
2525                        "%s\n", nt_errstr(status));
2526                 goto fail;
2527         } else {
2528                 printf("pid1 successfully wrote to the range 130:4\n");
2529         }
2530
2531         cli_setpid(cli1, 2);
2532
2533         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2534         if (!NT_STATUS_IS_OK(status)) {
2535                 printf("pid2 unable to read the range 130:4, error was "
2536                        "%s\n", nt_errstr(status));
2537                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2538                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2539                         goto fail;
2540                 }
2541         } else {
2542                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2543                        (unsigned long)nread);
2544                 goto fail;
2545         }
2546
2547         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2548         if (!NT_STATUS_IS_OK(status)) {
2549                 printf("pid2 unable to write to the range 130:4, error was "
2550                        "%s\n", nt_errstr(status));
2551                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2552                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2553                         goto fail;
2554                 }
2555         } else {
2556                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2557                 goto fail;
2558         }
2559
2560         cli_unlock(cli1, fnum1, 130, 0);
2561         correct = True;
2562
2563 fail:
2564         cli_close(cli1, fnum1);
2565         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2566         torture_close_connection(cli1);
2567
2568         printf("finished locktest7\n");
2569         return correct;
2570 }
2571
2572 /*
2573  * This demonstrates a problem with our use of GPFS share modes: A file
2574  * descriptor sitting in the pending close queue holding a GPFS share mode
2575  * blocks opening a file another time. Happens with Word 2007 temp files.
2576  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2577  * open is denied with NT_STATUS_SHARING_VIOLATION.
2578  */
2579
2580 static bool run_locktest8(int dummy)
2581 {
2582         struct cli_state *cli1;
2583         const char *fname = "\\lockt8.lck";
2584         uint16_t fnum1, fnum2;
2585         char buf[200];
2586         bool correct = False;
2587         NTSTATUS status;
2588
2589         if (!torture_open_connection(&cli1, 0)) {
2590                 return False;
2591         }
2592
2593         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2594
2595         printf("starting locktest8\n");
2596
2597         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2598
2599         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2600                           &fnum1);
2601         if (!NT_STATUS_IS_OK(status)) {
2602                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2603                 return false;
2604         }
2605
2606         memset(buf, 0, sizeof(buf));
2607
2608         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2609         if (!NT_STATUS_IS_OK(status)) {
2610                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2611                           nt_errstr(status));
2612                 goto fail;
2613         }
2614
2615         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2616         if (!NT_STATUS_IS_OK(status)) {
2617                 printf("Unable to apply read lock on range 1:1, error was "
2618                        "%s\n", nt_errstr(status));
2619                 goto fail;
2620         }
2621
2622         status = cli_close(cli1, fnum1);
2623         if (!NT_STATUS_IS_OK(status)) {
2624                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2625                 goto fail;
2626         }
2627
2628         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2629         if (!NT_STATUS_IS_OK(status)) {
2630                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2631                           nt_errstr(status));
2632                 goto fail;
2633         }
2634
2635         correct = true;
2636
2637 fail:
2638         cli_close(cli1, fnum1);
2639         cli_close(cli1, fnum2);
2640         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2641         torture_close_connection(cli1);
2642
2643         printf("finished locktest8\n");
2644         return correct;
2645 }
2646
2647 /*
2648  * This test is designed to be run in conjunction with
2649  * external NFS or POSIX locks taken in the filesystem.
2650  * It checks that the smbd server will block until the
2651  * lock is released and then acquire it. JRA.
2652  */
2653
2654 static bool got_alarm;
2655 static struct cli_state *alarm_cli;
2656
2657 static void alarm_handler(int dummy)
2658 {
2659         got_alarm = True;
2660 }
2661
2662 static void alarm_handler_parent(int dummy)
2663 {
2664         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2665 }
2666
2667 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2668 {
2669         int fd;
2670         char c = '\0';
2671         struct flock lock;
2672         const char *local_pathname = NULL;
2673         int ret;
2674
2675         local_pathname = talloc_asprintf(talloc_tos(),
2676                         "%s/%s", local_path, fname);
2677         if (!local_pathname) {
2678                 printf("child: alloc fail\n");
2679                 exit(1);
2680         }
2681
2682         unlink(local_pathname);
2683         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2684         if (fd == -1) {
2685                 printf("child: open of %s failed %s.\n",
2686                         local_pathname, strerror(errno));
2687                 exit(1);
2688         }
2689
2690         /* Now take a fcntl lock. */
2691         lock.l_type = F_WRLCK;
2692         lock.l_whence = SEEK_SET;
2693         lock.l_start = 0;
2694         lock.l_len = 4;
2695         lock.l_pid = getpid();
2696
2697         ret = fcntl(fd,F_SETLK,&lock);
2698         if (ret == -1) {
2699                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2700                         local_pathname, strerror(errno));
2701                 exit(1);
2702         } else {
2703                 printf("child: got lock 0:4 on file %s.\n",
2704                         local_pathname );
2705                 fflush(stdout);
2706         }
2707
2708         CatchSignal(SIGALRM, alarm_handler);
2709         alarm(5);
2710         /* Signal the parent. */
2711         if (write(write_fd, &c, 1) != 1) {
2712                 printf("child: start signal fail %s.\n",
2713                         strerror(errno));
2714                 exit(1);
2715         }
2716         alarm(0);
2717
2718         alarm(10);
2719         /* Wait for the parent to be ready. */
2720         if (read(read_fd, &c, 1) != 1) {
2721                 printf("child: reply signal fail %s.\n",
2722                         strerror(errno));
2723                 exit(1);
2724         }
2725         alarm(0);
2726
2727         sleep(5);
2728         close(fd);
2729         printf("child: released lock 0:4 on file %s.\n",
2730                 local_pathname );
2731         fflush(stdout);
2732         exit(0);
2733 }
2734
2735 static bool _run_locktest9X(const char *fname, int timeout)
2736 {
2737         struct cli_state *cli1;
2738         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2739         uint16_t fnum;
2740         bool correct = False;
2741         int pipe_in[2], pipe_out[2];
2742         pid_t child_pid;
2743         char c = '\0';
2744         int ret;
2745         struct timeval start;
2746         double seconds;
2747         NTSTATUS status;
2748
2749         printf("starting locktest9X: %s\n", fname);
2750
2751         if (local_path == NULL) {
2752                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2753                 return false;
2754         }
2755
2756         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2757                 return false;
2758         }
2759
2760         child_pid = fork();
2761         if (child_pid == -1) {
2762                 return false;
2763         }
2764
2765         if (child_pid == 0) {
2766                 /* Child. */
2767                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2768                 exit(0);
2769         }
2770
2771         close(pipe_out[0]);
2772         close(pipe_in[1]);
2773         pipe_out[0] = -1;
2774         pipe_in[1] = -1;
2775
2776         /* Parent. */
2777         ret = read(pipe_in[0], &c, 1);
2778         if (ret != 1) {
2779                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2780                         strerror(errno));
2781                 return false;
2782         }
2783
2784         if (!torture_open_connection(&cli1, 0)) {
2785                 return false;
2786         }
2787
2788         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2789
2790         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2791                           &fnum);
2792         if (!NT_STATUS_IS_OK(status)) {
2793                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2794                 return false;
2795         }
2796
2797         /* Ensure the child has the lock. */
2798         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2799         if (NT_STATUS_IS_OK(status)) {
2800                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2801                 goto fail;
2802         } else {
2803                 d_printf("Child has the lock.\n");
2804         }
2805
2806         /* Tell the child to wait 5 seconds then exit. */
2807         ret = write(pipe_out[1], &c, 1);
2808         if (ret != 1) {
2809                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2810                         strerror(errno));
2811                 goto fail;
2812         }
2813
2814         /* Wait 20 seconds for the lock. */
2815         alarm_cli = cli1;
2816         CatchSignal(SIGALRM, alarm_handler_parent);
2817         alarm(20);
2818
2819         start = timeval_current();
2820
2821         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2822         if (!NT_STATUS_IS_OK(status)) {
2823                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2824                        "%s\n", nt_errstr(status));
2825                 goto fail_nofd;
2826         }
2827         alarm(0);
2828
2829         seconds = timeval_elapsed(&start);
2830
2831         printf("Parent got the lock after %.2f seconds.\n",
2832                 seconds);
2833
2834         status = cli_close(cli1, fnum);
2835         if (!NT_STATUS_IS_OK(status)) {
2836                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2837                 goto fail;
2838         }
2839
2840         correct = true;
2841
2842 fail:
2843         cli_close(cli1, fnum);
2844         torture_close_connection(cli1);
2845
2846 fail_nofd:
2847
2848         printf("finished locktest9X: %s\n", fname);
2849         return correct;
2850 }
2851
2852 static bool run_locktest9a(int dummy)
2853 {
2854         return _run_locktest9X("lock9a.dat", -1);
2855 }
2856
2857 static bool run_locktest9b(int dummy)
2858 {
2859         return _run_locktest9X("lock9b.dat", 10000);
2860 }
2861
2862 struct locktest10_state {
2863         bool ok;
2864         bool done;
2865 };
2866
2867 static void locktest10_lockingx_done(struct tevent_req *subreq);
2868 static void locktest10_read_andx_done(struct tevent_req *subreq);
2869
2870 static bool run_locktest10(int dummy)
2871 {
2872         struct tevent_context *ev = NULL;
2873         struct cli_state *cli1 = NULL;
2874         struct cli_state *cli2 = NULL;
2875         struct smb1_lock_element lck = { 0 };
2876         struct tevent_req *reqs[2] = { NULL };
2877         struct tevent_req *smbreqs[2] = { NULL };
2878         const char fname[] = "\\lockt10.lck";
2879         uint16_t fnum1, fnum2;
2880         bool ret = false;
2881         bool ok;
2882         uint8_t data = 1;
2883         struct locktest10_state state = { .ok = true };
2884         NTSTATUS status;
2885
2886         printf("starting locktest10\n");
2887
2888         ev = samba_tevent_context_init(NULL);
2889         if (ev == NULL) {
2890                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2891                 goto done;
2892         }
2893
2894         ok = torture_open_connection(&cli1, 0);
2895         if (!ok) {
2896                 goto done;
2897         }
2898         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2899
2900         ok = torture_open_connection(&cli2, 1);
2901         if (!ok) {
2902                 goto done;
2903         }
2904         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2905
2906         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2907         if (!NT_STATUS_IS_OK(status)) {
2908                 d_fprintf(stderr,
2909                           "cli_openx failed: %s\n",
2910                           nt_errstr(status));
2911                 goto done;
2912         }
2913
2914         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2915         if (!NT_STATUS_IS_OK(status)) {
2916                 d_fprintf(stderr,
2917                           "cli_writeall failed: %s\n",
2918                           nt_errstr(status));
2919                 goto done;
2920         }
2921
2922         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2923         if (!NT_STATUS_IS_OK(status)) {
2924                 d_fprintf(stderr,
2925                           "cli_openx failed: %s\n",
2926                           nt_errstr(status));
2927                 goto done;
2928         }
2929
2930         status = cli_locktype(
2931                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2932         if (!NT_STATUS_IS_OK(status)) {
2933                 d_fprintf(stderr,
2934                           "cli_locktype failed: %s\n",
2935                           nt_errstr(status));
2936                 goto done;
2937         }
2938
2939         lck = (struct smb1_lock_element) {
2940                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2941         };
2942
2943         reqs[0] = cli_lockingx_create(
2944                 ev,                             /* mem_ctx */
2945                 ev,                             /* tevent_context */
2946                 cli1,                           /* cli */
2947                 fnum1,                          /* fnum */
2948                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2949                 0,                              /* newoplocklevel */
2950                 1,                              /* timeout */
2951                 0,                              /* num_unlocks */
2952                 NULL,                           /* unlocks */
2953                 1,                              /* num_locks */
2954                 &lck,                           /* locks */
2955                 &smbreqs[0]);                   /* psmbreq */
2956         if (reqs[0] == NULL) {
2957                 d_fprintf(stderr, "cli_lockingx_create failed\n");
2958                 goto done;
2959         }
2960         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2961
2962         reqs[1] = cli_read_andx_create(
2963                 ev,             /* mem_ctx */
2964                 ev,             /* ev */
2965                 cli1,           /* cli */
2966                 fnum1,          /* fnum */
2967                 0,              /* offset */
2968                 1,              /* size */
2969                 &smbreqs[1]);   /* psmbreq */
2970         if (reqs[1] == NULL) {
2971                 d_fprintf(stderr, "cli_read_andx_create failed\n");
2972                 goto done;
2973         }
2974         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2975
2976         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2977         if (!NT_STATUS_IS_OK(status)) {
2978                 d_fprintf(stderr,
2979                           "smb1cli_req_chain_submit failed: %s\n",
2980                           nt_errstr(status));
2981                 goto done;
2982         }
2983
2984         while (!state.done) {
2985                 tevent_loop_once(ev);
2986         }
2987
2988         torture_close_connection(cli1);
2989
2990         if (state.ok) {
2991                 ret = true;
2992         }
2993 done:
2994         return ret;
2995 }
2996
2997 static void locktest10_lockingx_done(struct tevent_req *subreq)
2998 {
2999         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3000         NTSTATUS status;
3001
3002         status = cli_lockingx_recv(subreq);
3003         TALLOC_FREE(subreq);
3004
3005         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3006                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3007                 state->ok = false;
3008         }
3009 }
3010
3011 static void locktest10_read_andx_done(struct tevent_req *subreq)
3012 {
3013         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3014         ssize_t received = -1;
3015         uint8_t *rcvbuf = NULL;
3016         NTSTATUS status;
3017
3018         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3019
3020         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3021                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3022                 state->ok = false;
3023         }
3024
3025         state->done = true;
3026         TALLOC_FREE(subreq);
3027 }
3028
3029 static bool run_locktest11(int dummy)
3030 {
3031         struct cli_state *cli1;
3032         const char *fname = "\\lockt11.lck";
3033         NTSTATUS status;
3034         uint16_t fnum;
3035         bool ret = false;
3036
3037         if (!torture_open_connection(&cli1, 0)) {
3038                 return false;
3039         }
3040
3041         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3042
3043         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3044
3045         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3046         if (!NT_STATUS_IS_OK(status)) {
3047                 d_fprintf(stderr,
3048                           "cli_openx returned %s\n",
3049                           nt_errstr(status));
3050                 return false;
3051         }
3052
3053         /*
3054          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3055          * returns NT_STATUS_OK
3056          */
3057
3058         status = cli_lockingx(
3059                 cli1,                           /* cli */
3060                 fnum,                           /* fnum */
3061                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3062                 0,                              /* newoplocklevel */
3063                 0,                              /* timeout */
3064                 0,                              /* num_unlocks */
3065                 NULL,                           /* unlocks */
3066                 0,                              /* num_locks */
3067                 NULL);                          /* locks */
3068
3069         if (!NT_STATUS_IS_OK(status)) {
3070                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3071                 goto fail;
3072         }
3073
3074         ret = true;
3075 fail:
3076         cli_close(cli1, fnum);
3077         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3078
3079         return ret;
3080 }
3081
3082 struct deferred_close_state {
3083         struct tevent_context *ev;
3084         struct cli_state *cli;
3085         uint16_t fnum;
3086 };
3087
3088 static void deferred_close_waited(struct tevent_req *subreq);
3089 static void deferred_close_done(struct tevent_req *subreq);
3090
3091 static struct tevent_req *deferred_close_send(
3092         TALLOC_CTX *mem_ctx,
3093         struct tevent_context *ev,
3094         int wait_secs,
3095         struct cli_state *cli,
3096         uint16_t fnum)
3097 {
3098         struct tevent_req *req = NULL, *subreq = NULL;
3099         struct deferred_close_state *state = NULL;
3100         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3101
3102         req = tevent_req_create(
3103                 mem_ctx, &state, struct deferred_close_state);
3104         if (req == NULL) {
3105                 return NULL;
3106         }
3107         state->ev = ev;
3108         state->cli = cli;
3109         state->fnum = fnum;
3110
3111         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3112         if (tevent_req_nomem(subreq, req)) {
3113                 return tevent_req_post(req, ev);
3114         }
3115         tevent_req_set_callback(subreq, deferred_close_waited, req);
3116         return req;
3117 }
3118
3119 static void deferred_close_waited(struct tevent_req *subreq)
3120 {
3121         struct tevent_req *req = tevent_req_callback_data(
3122                 subreq, struct tevent_req);
3123         struct deferred_close_state *state = tevent_req_data(
3124                 req, struct deferred_close_state);
3125         bool ok;
3126
3127         ok = tevent_wakeup_recv(subreq);
3128         TALLOC_FREE(subreq);
3129         if (!ok) {
3130                 tevent_req_oom(req);
3131                 return;
3132         }
3133
3134         subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3135         if (tevent_req_nomem(subreq, req)) {
3136                 return;
3137         }
3138         tevent_req_set_callback(subreq, deferred_close_done, req);
3139 }
3140
3141 static void deferred_close_done(struct tevent_req *subreq)
3142 {
3143         NTSTATUS status = cli_close_recv(subreq);
3144         tevent_req_simple_finish_ntstatus(subreq, status);
3145 }
3146
3147 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3148 {
3149         return tevent_req_simple_recv_ntstatus(req);
3150 }
3151
3152 struct lockread_state {
3153         struct smb1_lock_element lck;
3154         struct tevent_req *reqs[2];
3155         struct tevent_req *smbreqs[2];
3156         NTSTATUS lock_status;
3157         NTSTATUS read_status;
3158         uint8_t *readbuf;
3159 };
3160
3161 static void lockread_lockingx_done(struct tevent_req *subreq);
3162 static void lockread_read_andx_done(struct tevent_req *subreq);
3163
3164 static struct tevent_req *lockread_send(
3165         TALLOC_CTX *mem_ctx,
3166         struct tevent_context *ev,
3167         struct cli_state *cli,
3168         uint16_t fnum)
3169 {
3170         struct tevent_req *req = NULL;
3171         struct lockread_state *state = NULL;
3172         NTSTATUS status;
3173
3174         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3175         if (req == NULL) {
3176                 return NULL;
3177         }
3178
3179         state->lck = (struct smb1_lock_element) {
3180                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3181         };
3182
3183         state->reqs[0] = cli_lockingx_create(
3184                 ev,                             /* mem_ctx */
3185                 ev,                             /* tevent_context */
3186                 cli,                            /* cli */
3187                 fnum,                           /* fnum */
3188                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3189                 0,                              /* newoplocklevel */
3190                 10000,                          /* timeout */
3191                 0,                              /* num_unlocks */
3192                 NULL,                           /* unlocks */
3193                 1,                              /* num_locks */
3194                 &state->lck,                    /* locks */
3195                 &state->smbreqs[0]);            /* psmbreq */
3196         if (tevent_req_nomem(state->reqs[0], req)) {
3197                 return tevent_req_post(req, ev);
3198         }
3199         tevent_req_set_callback(
3200                 state->reqs[0], lockread_lockingx_done, req);
3201
3202         state->reqs[1] = cli_read_andx_create(
3203                 ev,             /* mem_ctx */
3204                 ev,             /* ev */
3205                 cli,            /* cli */
3206                 fnum,           /* fnum */
3207                 0,              /* offset */
3208                 1,              /* size */
3209                 &state->smbreqs[1]);    /* psmbreq */
3210         if (tevent_req_nomem(state->reqs[1], req)) {
3211                 return tevent_req_post(req, ev);
3212         }
3213         tevent_req_set_callback(
3214                 state->reqs[1], lockread_read_andx_done, req);
3215
3216         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3217         if (tevent_req_nterror(req, status)) {
3218                 return tevent_req_post(req, ev);
3219         }
3220         return req;
3221 }
3222
3223 static void lockread_lockingx_done(struct tevent_req *subreq)
3224 {
3225         struct tevent_req *req = tevent_req_callback_data(
3226                 subreq, struct tevent_req);
3227         struct lockread_state *state = tevent_req_data(
3228                 req, struct lockread_state);
3229         state->lock_status = cli_lockingx_recv(subreq);
3230         TALLOC_FREE(subreq);
3231         d_fprintf(stderr,
3232                   "lockingx returned %s\n",
3233                   nt_errstr(state->lock_status));
3234 }
3235
3236 static void lockread_read_andx_done(struct tevent_req *subreq)
3237 {
3238         struct tevent_req *req = tevent_req_callback_data(
3239                 subreq, struct tevent_req);
3240         struct lockread_state *state = tevent_req_data(
3241                 req, struct lockread_state);
3242         ssize_t received = -1;
3243         uint8_t *rcvbuf = NULL;
3244
3245         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3246
3247         d_fprintf(stderr,
3248                   "read returned %s\n",
3249                   nt_errstr(state->read_status));
3250
3251         if (!NT_STATUS_IS_OK(state->read_status)) {
3252                 TALLOC_FREE(subreq);
3253                 tevent_req_done(req);
3254                 return;
3255         }
3256
3257         if (received > 0) {
3258                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3259                 TALLOC_FREE(subreq);
3260                 if (tevent_req_nomem(state->readbuf, req)) {
3261                         return;
3262                 }
3263         }
3264         TALLOC_FREE(subreq);
3265         tevent_req_done(req);
3266 }
3267
3268 static NTSTATUS lockread_recv(
3269         struct tevent_req *req,
3270         NTSTATUS *lock_status,
3271         NTSTATUS *read_status,
3272         TALLOC_CTX *mem_ctx,
3273         uint8_t **read_buf)
3274 {
3275         struct lockread_state *state = tevent_req_data(
3276                 req, struct lockread_state);
3277         NTSTATUS status;
3278
3279         if (tevent_req_is_nterror(req, &status)) {
3280                 return status;
3281         }
3282
3283         *lock_status = state->lock_status;
3284         *read_status = state->read_status;
3285         if (state->readbuf != NULL) {
3286                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3287         } else {
3288                 *read_buf = NULL;
3289         }
3290
3291         return NT_STATUS_OK;
3292 }
3293
3294 struct lock12_state {
3295         uint8_t dummy;
3296 };
3297
3298 static void lock12_closed(struct tevent_req *subreq);
3299 static void lock12_read(struct tevent_req *subreq);
3300
3301 static struct tevent_req *lock12_send(
3302         TALLOC_CTX *mem_ctx,
3303         struct tevent_context *ev,
3304         struct cli_state *cli,
3305         uint16_t fnum1,
3306         uint16_t fnum2)
3307 {
3308         struct tevent_req *req = NULL, *subreq = NULL;
3309         struct lock12_state *state = NULL;
3310
3311         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3312         if (req == NULL) {
3313                 return NULL;
3314         }
3315
3316         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3317         if (tevent_req_nomem(subreq, req)) {
3318                 return tevent_req_post(req, ev);
3319         }
3320         tevent_req_set_callback(subreq, lock12_closed, req);
3321
3322         subreq = lockread_send(state, ev, cli, fnum2);
3323         if (tevent_req_nomem(subreq, req)) {
3324                 return tevent_req_post(req, ev);
3325         }
3326         tevent_req_set_callback(subreq, lock12_read, req);
3327
3328         return req;
3329 }
3330
3331 static void lock12_closed(struct tevent_req *subreq)
3332 {
3333         struct tevent_req *req = tevent_req_callback_data(
3334                 subreq, struct tevent_req);
3335         NTSTATUS status;
3336
3337         status = deferred_close_recv(subreq);
3338         TALLOC_FREE(subreq);
3339         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3340         if (tevent_req_nterror(req, status)) {
3341                 return;
3342         }
3343 }
3344
3345 static void lock12_read(struct tevent_req *subreq)
3346 {
3347         struct tevent_req *req = tevent_req_callback_data(
3348                 subreq, struct tevent_req);
3349         struct lock12_state *state = tevent_req_data(
3350                 req, struct lock12_state);
3351         NTSTATUS status, lock_status, read_status;
3352         uint8_t *buf = NULL;
3353
3354         status = lockread_recv(
3355                 subreq, &lock_status, &read_status, state, &buf);
3356         TALLOC_FREE(subreq);
3357         if (tevent_req_nterror(req, status) ||
3358             tevent_req_nterror(req, lock_status) ||
3359             tevent_req_nterror(req, read_status)) {
3360                 return;
3361         }
3362         tevent_req_done(req);
3363 }
3364
3365 static NTSTATUS lock12_recv(struct tevent_req *req)
3366
3367 {
3368         NTSTATUS status;
3369
3370         if (tevent_req_is_nterror(req, &status)) {
3371                 return status;
3372         }
3373         return NT_STATUS_OK;
3374 }
3375
3376 static bool run_locktest12(int dummy)
3377 {
3378         struct tevent_context *ev = NULL;
3379         struct tevent_req *req = NULL;
3380         struct cli_state *cli = NULL;
3381         const char fname[] = "\\lockt12.lck";
3382         uint16_t fnum1, fnum2;
3383         bool ret = false;
3384         bool ok;
3385         uint8_t data = 1;
3386         NTSTATUS status;
3387
3388         printf("starting locktest12\n");
3389
3390         ev = samba_tevent_context_init(NULL);
3391         if (ev == NULL) {
3392                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3393                 goto done;
3394         }
3395
3396         ok = torture_open_connection(&cli, 0);
3397         if (!ok) {
3398                 goto done;
3399         }
3400         smbXcli_conn_set_sockopt(cli->conn, sockops);
3401
3402         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3403         if (!NT_STATUS_IS_OK(status)) {
3404                 d_fprintf(stderr,
3405                           "cli_openx failed: %s\n",
3406                           nt_errstr(status));
3407                 goto done;
3408         }
3409
3410         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3411         if (!NT_STATUS_IS_OK(status)) {
3412                 d_fprintf(stderr,
3413                           "cli_openx failed: %s\n",
3414                           nt_errstr(status));
3415                 goto done;
3416         }
3417
3418         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3419         if (!NT_STATUS_IS_OK(status)) {
3420                 d_fprintf(stderr,
3421                           "cli_writeall failed: %s\n",
3422                           nt_errstr(status));
3423                 goto done;
3424         }
3425
3426         status = cli_locktype(
3427                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3428         if (!NT_STATUS_IS_OK(status)) {
3429                 d_fprintf(stderr,
3430                           "cli_locktype failed: %s\n",
3431                           nt_errstr(status));
3432                 goto done;
3433         }
3434
3435         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3436         if (req == NULL) {
3437                 d_fprintf(stderr, "lock12_send failed\n");
3438                 goto done;
3439         }
3440
3441         ok = tevent_req_poll_ntstatus(req, ev, &status);
3442         if (!ok) {
3443                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3444                 goto done;
3445         }
3446
3447         if (!NT_STATUS_IS_OK(status)) {
3448                 d_fprintf(stderr,
3449                           "tevent_req_poll_ntstatus returned %s\n",
3450                           nt_errstr(status));
3451                 goto done;
3452         }
3453
3454         status = lock12_recv(req);
3455         if (!NT_STATUS_IS_OK(status)) {
3456                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3457                 goto done;
3458         }
3459
3460         ret = true;
3461 done:
3462         if (cli != NULL) {
3463                 torture_close_connection(cli);
3464         }
3465         return ret;
3466 }
3467
3468 struct lock_ntcancel_state {
3469         struct timeval start;
3470         struct smb1_lock_element lck;
3471         struct tevent_req *subreq;
3472 };
3473
3474 static void lock_ntcancel_waited(struct tevent_req *subreq);
3475 static void lock_ntcancel_done(struct tevent_req *subreq);
3476
3477 static struct tevent_req *lock_ntcancel_send(
3478         TALLOC_CTX *mem_ctx,
3479         struct tevent_context *ev,
3480         struct cli_state *cli,
3481         uint16_t fnum)
3482 {
3483         struct tevent_req *req = NULL, *subreq = NULL;
3484         struct lock_ntcancel_state *state = NULL;
3485
3486         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3487         if (req == NULL) {
3488                 return NULL;
3489         }
3490         state->lck = (struct smb1_lock_element) {
3491                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3492         };
3493         state->start = timeval_current();
3494
3495         state->subreq = cli_lockingx_send(
3496                 state,                          /* mem_ctx */
3497                 ev,                             /* tevent_context */
3498                 cli,                            /* cli */
3499                 fnum,                           /* fnum */
3500                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3501                 0,                              /* newoplocklevel */
3502                 10000,                          /* timeout */
3503                 0,                              /* num_unlocks */
3504                 NULL,                           /* unlocks */
3505                 1,                              /* num_locks */
3506                 &state->lck);                   /* locks */
3507         if (tevent_req_nomem(state->subreq, req)) {
3508                 return tevent_req_post(req, ev);
3509         }
3510         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3511
3512         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3513         if (tevent_req_nomem(subreq, req)) {
3514                 return tevent_req_post(req, ev);
3515         }
3516         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3517         return req;
3518 }
3519
3520 static void lock_ntcancel_waited(struct tevent_req *subreq)
3521 {
3522         struct tevent_req *req = tevent_req_callback_data(
3523                 subreq, struct tevent_req);
3524         struct lock_ntcancel_state *state = tevent_req_data(
3525                 req, struct lock_ntcancel_state);
3526         bool ok;
3527
3528         ok = tevent_wakeup_recv(subreq);
3529         TALLOC_FREE(subreq);
3530         if (!ok) {
3531                 tevent_req_oom(req);
3532                 return;
3533         }
3534
3535         ok = tevent_req_cancel(state->subreq);
3536         if (!ok) {
3537                 d_fprintf(stderr, "Could not cancel subreq\n");
3538                 tevent_req_oom(req);
3539                 return;
3540         }
3541 }
3542
3543 static void lock_ntcancel_done(struct tevent_req *subreq)
3544 {
3545         struct tevent_req *req = tevent_req_callback_data(
3546                 subreq, struct tevent_req);
3547         struct lock_ntcancel_state *state = tevent_req_data(
3548                 req, struct lock_ntcancel_state);
3549         NTSTATUS status;
3550         double elapsed;
3551
3552         status = cli_lockingx_recv(subreq);
3553         TALLOC_FREE(subreq);
3554
3555         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3556                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3557                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3558                 return;
3559         }
3560
3561         elapsed = timeval_elapsed(&state->start);
3562
3563         if (elapsed > 3) {
3564                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3565                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3566                 return;
3567         }
3568
3569         tevent_req_done(req);
3570 }
3571
3572 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3573 {
3574         return tevent_req_simple_recv_ntstatus(req);
3575 }
3576
3577 static bool run_locktest13(int dummy)
3578 {
3579         struct tevent_context *ev = NULL;
3580         struct tevent_req *req = NULL;
3581         struct cli_state *cli = NULL;
3582         const char fname[] = "\\lockt13.lck";
3583         uint16_t fnum1, fnum2;
3584         bool ret = false;
3585         bool ok;
3586         uint8_t data = 1;
3587         NTSTATUS status;
3588
3589         printf("starting locktest13\n");
3590
3591         ev = samba_tevent_context_init(NULL);
3592         if (ev == NULL) {
3593                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3594                 goto done;
3595         }
3596
3597         ok = torture_open_connection(&cli, 0);
3598         if (!ok) {
3599                 goto done;
3600         }
3601         smbXcli_conn_set_sockopt(cli->conn, sockops);
3602
3603         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3604         if (!NT_STATUS_IS_OK(status)) {
3605                 d_fprintf(stderr,
3606                           "cli_openx failed: %s\n",
3607                           nt_errstr(status));
3608                 goto done;
3609         }
3610
3611         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3612         if (!NT_STATUS_IS_OK(status)) {
3613                 d_fprintf(stderr,
3614                           "cli_openx failed: %s\n",
3615                           nt_errstr(status));
3616                 goto done;
3617         }
3618
3619         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3620         if (!NT_STATUS_IS_OK(status)) {
3621                 d_fprintf(stderr,
3622                           "cli_writeall failed: %s\n",
3623                           nt_errstr(status));
3624                 goto done;
3625         }
3626
3627         status = cli_locktype(
3628                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3629         if (!NT_STATUS_IS_OK(status)) {
3630                 d_fprintf(stderr,
3631                           "cli_locktype failed: %s\n",
3632                           nt_errstr(status));
3633                 goto done;
3634         }
3635
3636         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3637         if (req == NULL) {
3638                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3639                 goto done;
3640         }
3641
3642         ok = tevent_req_poll_ntstatus(req, ev, &status);
3643         if (!ok) {
3644                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3645                 goto done;
3646         }
3647
3648         if (!NT_STATUS_IS_OK(status)) {
3649                 d_fprintf(stderr,
3650                           "tevent_req_poll_ntstatus returned %s\n",
3651                           nt_errstr(status));
3652                 goto done;
3653         }
3654
3655         status = lock_ntcancel_recv(req);
3656         if (!NT_STATUS_IS_OK(status)) {
3657                 d_fprintf(stderr,
3658                           "lock_ntcancel returned %s\n",
3659                           nt_errstr(status));
3660                 goto done;
3661         }
3662
3663         ret = true;
3664 done:
3665         if (cli != NULL) {
3666                 torture_close_connection(cli);
3667         }
3668         return ret;
3669 }
3670
3671 /*
3672 test whether fnums and tids open on one VC are available on another (a major
3673 security hole)
3674 */
3675 static bool run_fdpasstest(int dummy)
3676 {
3677         struct cli_state *cli1, *cli2;
3678         const char *fname = "\\fdpass.tst";
3679         uint16_t fnum1;
3680         char buf[1024];
3681         NTSTATUS status;
3682
3683         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3684                 return False;
3685         }
3686         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3687         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3688
3689         printf("starting fdpasstest\n");
3690
3691         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3692
3693         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3694                           &fnum1);
3695         if (!NT_STATUS_IS_OK(status)) {
3696                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3697                 return False;
3698         }
3699
3700         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3701                               13, NULL);
3702         if (!NT_STATUS_IS_OK(status)) {
3703                 printf("write failed (%s)\n", nt_errstr(status));
3704                 return False;
3705         }
3706
3707         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3708         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3709         cli_setpid(cli2, cli_getpid(cli1));
3710
3711         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3712                 printf("read succeeded! nasty security hole [%s]\n", buf);
3713                 return false;
3714         }
3715
3716         cli_close(cli1, fnum1);
3717         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3718
3719         torture_close_connection(cli1);
3720         torture_close_connection(cli2);
3721
3722         printf("finished fdpasstest\n");
3723         return True;
3724 }
3725
3726 static bool run_fdsesstest(int dummy)
3727 {
3728         struct cli_state *cli;
3729         uint16_t new_vuid;
3730         uint16_t saved_vuid;
3731         uint32_t new_cnum;
3732         uint32_t saved_cnum;
3733         const char *fname = "\\fdsess.tst";
3734         const char *fname1 = "\\fdsess1.tst";
3735         uint16_t fnum1;
3736         uint16_t fnum2;
3737         char buf[1024];
3738         bool ret = True;
3739         NTSTATUS status;
3740
3741         if (!torture_open_connection(&cli, 0))
3742                 return False;
3743         smbXcli_conn_set_sockopt(cli->conn, sockops);
3744
3745         if (!torture_cli_session_setup2(cli, &new_vuid))
3746                 return False;
3747
3748         saved_cnum = cli_state_get_tid(cli);
3749         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3750                 return False;
3751         new_cnum = cli_state_get_tid(cli);
3752         cli_state_set_tid(cli, saved_cnum);
3753
3754         printf("starting fdsesstest\n");
3755
3756         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3757         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3758
3759         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3760         if (!NT_STATUS_IS_OK(status)) {
3761                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3762                 return False;
3763         }
3764
3765         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3766                               NULL);
3767         if (!NT_STATUS_IS_OK(status)) {
3768                 printf("write failed (%s)\n", nt_errstr(status));
3769                 return False;
3770         }
3771
3772         saved_vuid = cli_state_get_uid(cli);
3773         cli_state_set_uid(cli, new_vuid);
3774
3775         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3776                 printf("read succeeded with different vuid! "
3777                        "nasty security hole [%s]\n", buf);
3778                 ret = false;
3779         }
3780         /* Try to open a file with different vuid, samba cnum. */
3781         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3782                 printf("create with different vuid, same cnum succeeded.\n");
3783                 cli_close(cli, fnum2);
3784                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3785         } else {
3786                 printf("create with different vuid, same cnum failed.\n");
3787                 printf("This will cause problems with service clients.\n");
3788                 ret = False;
3789         }
3790
3791         cli_state_set_uid(cli, saved_vuid);
3792
3793         /* Try with same vuid, different cnum. */
3794         cli_state_set_tid(cli, new_cnum);
3795
3796         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3797                 printf("read succeeded with different cnum![%s]\n", buf);
3798                 ret = false;
3799         }
3800
3801         cli_state_set_tid(cli, saved_cnum);
3802         cli_close(cli, fnum1);
3803         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804
3805         torture_close_connection(cli);
3806
3807         printf("finished fdsesstest\n");
3808         return ret;
3809 }
3810
3811 /*
3812   This test checks that 
3813
3814   1) the server does not allow an unlink on a file that is open
3815 */
3816 static bool run_unlinktest(int dummy)
3817 {
3818         struct cli_state *cli;
3819         const char *fname = "\\unlink.tst";
3820         uint16_t fnum;
3821         bool correct = True;
3822         NTSTATUS status;
3823
3824         if (!torture_open_connection(&cli, 0)) {
3825                 return False;
3826         }
3827
3828         smbXcli_conn_set_sockopt(cli->conn, sockops);
3829
3830         printf("starting unlink test\n");
3831
3832         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3833
3834         cli_setpid(cli, 1);
3835
3836         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3837         if (!NT_STATUS_IS_OK(status)) {
3838                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3839                 return False;
3840         }
3841
3842         status = cli_unlink(cli, fname,
3843                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3844         if (NT_STATUS_IS_OK(status)) {
3845                 printf("error: server allowed unlink on an open file\n");
3846                 correct = False;
3847         } else {
3848                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3849                                       NT_STATUS_SHARING_VIOLATION);
3850         }
3851
3852         cli_close(cli, fnum);
3853         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3854
3855         if (!torture_close_connection(cli)) {
3856                 correct = False;
3857         }
3858
3859         printf("unlink test finished\n");
3860
3861         return correct;
3862 }
3863
3864
3865 /*
3866 test how many open files this server supports on the one socket
3867 */
3868 static bool run_maxfidtest(int dummy)
3869 {
3870         struct cli_state *cli;
3871         fstring fname;
3872         uint16_t fnums[0x11000];
3873         int i;
3874         int retries=4;
3875         bool correct = True;
3876         NTSTATUS status;
3877
3878         cli = current_cli;
3879
3880         if (retries <= 0) {
3881                 printf("failed to connect\n");
3882                 return False;
3883         }
3884
3885         smbXcli_conn_set_sockopt(cli->conn, sockops);
3886
3887         for (i=0; i<0x11000; i++) {
3888                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3889                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3890                                   &fnums[i]);
3891                 if (!NT_STATUS_IS_OK(status)) {
3892                         printf("open of %s failed (%s)\n", 
3893                                fname, nt_errstr(status));
3894                         printf("maximum fnum is %d\n", i);
3895                         break;
3896                 }
3897                 printf("%6d\r", i);
3898         }
3899         printf("%6d\n", i);
3900         i--;
3901
3902         printf("cleaning up\n");
3903         for (;i>=0;i--) {
3904                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3905                 cli_close(cli, fnums[i]);
3906
3907                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3908                 if (!NT_STATUS_IS_OK(status)) {
3909                         printf("unlink of %s failed (%s)\n", 
3910                                fname, nt_errstr(status));
3911                         correct = False;
3912                 }
3913                 printf("%6d\r", i);
3914         }
3915         printf("%6d\n", 0);
3916
3917         printf("maxfid test finished\n");
3918         if (!torture_close_connection(cli)) {
3919                 correct = False;
3920         }
3921         return correct;
3922 }
3923
3924 /* generate a random buffer */
3925 static void rand_buf(char *buf, int len)
3926 {
3927         while (len--) {
3928                 *buf = (char)sys_random();
3929                 buf++;
3930         }
3931 }
3932
3933 /* send smb negprot commands, not reading the response */
3934 static bool run_negprot_nowait(int dummy)
3935 {
3936         struct tevent_context *ev;
3937         int i;
3938         struct cli_state *cli;
3939         bool correct = True;
3940
3941         printf("starting negprot nowait test\n");
3942
3943         ev = samba_tevent_context_init(talloc_tos());
3944         if (ev == NULL) {
3945                 return false;
3946         }
3947
3948         if (!(cli = open_nbt_connection())) {
3949                 TALLOC_FREE(ev);
3950                 return False;
3951         }
3952
3953         for (i=0;i<50000;i++) {
3954                 struct tevent_req *req;
3955
3956                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3957                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3958                 if (req == NULL) {
3959                         TALLOC_FREE(ev);
3960                         return false;
3961                 }
3962                 if (!tevent_req_poll(req, ev)) {
3963                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3964                                   strerror(errno));
3965                         TALLOC_FREE(ev);
3966                         return false;
3967                 }
3968                 TALLOC_FREE(req);
3969         }
3970
3971         if (torture_close_connection(cli)) {
3972                 correct = False;
3973         }
3974
3975         printf("finished negprot nowait test\n");
3976
3977         return correct;
3978 }
3979
3980 /* send smb negprot commands, not reading the response */
3981 static bool run_bad_nbt_session(int dummy)
3982 {
3983         struct nmb_name called, calling;
3984         struct sockaddr_storage ss;
3985         NTSTATUS status;
3986         int fd;
3987         bool ret;
3988
3989         printf("starting bad nbt session test\n");
3990
3991         make_nmb_name(&calling, myname, 0x0);
3992         make_nmb_name(&called , host, 0x20);
3993
3994         if (!resolve_name(host, &ss, 0x20, true)) {
3995                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3996                 return false;
3997         }
3998
3999         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4000         if (!NT_STATUS_IS_OK(status)) {
4001                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4002                           nt_errstr(status));
4003                 return false;
4004         }
4005
4006         ret = cli_bad_session_request(fd, &calling, &called);
4007         close(fd);
4008         if (!ret) {
4009                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4010                           nt_errstr(status));
4011                 return false;
4012         }
4013
4014         printf("finished bad nbt session test\n");
4015         return true;
4016 }
4017
4018 /* send random IPC commands */
4019 static bool run_randomipc(int dummy)
4020 {
4021         char *rparam = NULL;
4022         char *rdata = NULL;
4023         unsigned int rdrcnt,rprcnt;
4024         char param[1024];
4025         int api, param_len, i;
4026         struct cli_state *cli;
4027         bool correct = True;
4028         int count = 50000;
4029
4030         printf("starting random ipc test\n");
4031
4032         if (!torture_open_connection(&cli, 0)) {
4033                 return False;
4034         }
4035
4036         for (i=0;i<count;i++) {
4037                 api = sys_random() % 500;
4038                 param_len = (sys_random() % 64);
4039
4040                 rand_buf(param, param_len);
4041
4042                 SSVAL(param,0,api); 
4043
4044                 cli_api(cli, 
4045                         param, param_len, 8,  
4046                         NULL, 0, CLI_BUFFER_SIZE,
4047                         &rparam, &rprcnt,     
4048                         &rdata, &rdrcnt);
4049                 if (i % 100 == 0) {
4050                         printf("%d/%d\r", i,count);
4051                 }
4052         }
4053         printf("%d/%d\n", i, count);
4054
4055         if (!torture_close_connection(cli)) {
4056                 correct = False;
4057         }
4058
4059         SAFE_FREE(rparam);
4060         SAFE_FREE(rdata);
4061
4062         printf("finished random ipc test\n");
4063
4064         return correct;
4065 }
4066
4067
4068
4069 static void browse_callback(const char *sname, uint32_t stype,
4070                             const char *comment, void *state)
4071 {
4072         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4073 }
4074
4075
4076
4077 /*
4078   This test checks the browse list code
4079
4080 */
4081 static bool run_browsetest(int dummy)
4082 {
4083         static struct cli_state *cli;
4084         bool correct = True;
4085
4086         printf("starting browse test\n");
4087
4088         if (!torture_open_connection(&cli, 0)) {
4089                 return False;
4090         }
4091
4092         printf("domain list:\n");
4093         cli_NetServerEnum(cli, cli->server_domain, 
4094                           SV_TYPE_DOMAIN_ENUM,
4095                           browse_callback, NULL);
4096
4097         printf("machine list:\n");
4098         cli_NetServerEnum(cli, cli->server_domain, 
4099                           SV_TYPE_ALL,
4100                           browse_callback, NULL);
4101
4102         if (!torture_close_connection(cli)) {
4103                 correct = False;
4104         }
4105
4106         printf("browse test finished\n");
4107
4108         return correct;
4109
4110 }
4111
4112 static bool check_attributes(struct cli_state *cli,
4113                                 const char *fname,
4114                                 uint32_t expected_attrs)
4115 {
4116         uint32_t attrs = 0;
4117         NTSTATUS status = cli_getatr(cli,
4118                                 fname,
4119                                 &attrs,
4120                                 NULL,
4121                                 NULL);
4122         if (!NT_STATUS_IS_OK(status)) {
4123                 printf("cli_getatr failed with %s\n",
4124                         nt_errstr(status));
4125                 return false;
4126         }
4127         if (attrs != expected_attrs) {
4128                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4129                         (unsigned int)attrs,
4130                         (unsigned int)expected_attrs);
4131                 return false;
4132         }
4133         return true;
4134 }
4135
4136 /*
4137   This checks how the getatr calls works
4138 */
4139 static bool run_attrtest(int dummy)
4140 {
4141         struct cli_state *cli;
4142         uint16_t fnum;
4143         time_t t, t2;
4144         const char *fname = "\\attrib123456789.tst";
4145         bool correct = True;
4146         NTSTATUS status;
4147
4148         printf("starting attrib test\n");
4149
4150         if (!torture_open_connection(&cli, 0)) {
4151                 return False;
4152         }
4153
4154         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4155         status = cli_unlink(cli, fname, 0x20000);
4156         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4157                 correct = false;
4158                 goto out;
4159         }
4160
4161         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4162         cli_openx(cli, fname, 
4163                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4164         cli_close(cli, fnum);
4165
4166         status = cli_getatr(cli, fname, NULL, NULL, &t);
4167         if (!NT_STATUS_IS_OK(status)) {
4168                 printf("getatr failed (%s)\n", nt_errstr(status));
4169                 correct = False;
4170         }
4171
4172         if (labs(t - time(NULL)) > 60*60*24*10) {
4173                 printf("ERROR: SMBgetatr bug. time is %s",
4174                        ctime(&t));
4175                 t = time(NULL);
4176                 correct = True;
4177         }
4178
4179         t2 = t-60*60*24; /* 1 day ago */
4180
4181         /* Ensure we can't set with out-of-range (unknown) attribute. */
4182         status = cli_setatr(cli, fname, 0x20000, t2);
4183         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4184                 correct = false;
4185                 goto out;
4186         }
4187
4188         status = cli_setatr(cli, fname, 0, t2);
4189         if (!NT_STATUS_IS_OK(status)) {
4190                 printf("setatr failed (%s)\n", nt_errstr(status));
4191                 correct = True;
4192         }
4193
4194         status = cli_getatr(cli, fname, NULL, NULL, &t);
4195         if (!NT_STATUS_IS_OK(status)) {
4196                 printf("getatr failed (%s)\n", nt_errstr(status));
4197                 correct = True;
4198         }
4199
4200         if (t != t2) {
4201                 printf("ERROR: getatr/setatr bug. times are\n%s",
4202                        ctime(&t));
4203                 printf("%s", ctime(&t2));
4204                 correct = True;
4205         }
4206
4207         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4208
4209         /* Check cli_setpathinfo_ext() */
4210         /* Re-create the file. */
4211         status = cli_openx(cli, fname,
4212                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4213         if (!NT_STATUS_IS_OK(status)) {
4214                 printf("Failed to recreate %s (%s)\n",
4215                         fname, nt_errstr(status));
4216                 correct = false;
4217         }
4218         cli_close(cli, fnum);
4219
4220         status = cli_setpathinfo_ext(
4221                 cli,
4222                 fname,
4223                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4224                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4225                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4226                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4227                 FILE_ATTRIBUTE_SYSTEM |
4228                 FILE_ATTRIBUTE_HIDDEN |
4229                 FILE_ATTRIBUTE_READONLY);
4230         if (!NT_STATUS_IS_OK(status)) {
4231                 printf("cli_setpathinfo_ext failed with %s\n",
4232                         nt_errstr(status));
4233                 correct = false;
4234         }
4235
4236         /* Check attributes are correct. */
4237         correct = check_attributes(cli,
4238                         fname,
4239                         FILE_ATTRIBUTE_SYSTEM |
4240                         FILE_ATTRIBUTE_HIDDEN |
4241                         FILE_ATTRIBUTE_READONLY);
4242         if (correct == false) {
4243                 goto out;
4244         }
4245
4246         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4247         status = cli_setpathinfo_ext(
4248                 cli,
4249                 fname,
4250                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4251                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4252                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4253                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4254                 FILE_ATTRIBUTE_NORMAL);
4255         if (!NT_STATUS_IS_OK(status)) {
4256                 printf("cli_setpathinfo_ext failed with %s\n",
4257                         nt_errstr(status));
4258                 correct = false;
4259         }
4260
4261         /* Check attributes are correct. */
4262         correct = check_attributes(cli,
4263                         fname,
4264                         FILE_ATTRIBUTE_SYSTEM |
4265                         FILE_ATTRIBUTE_HIDDEN |
4266                         FILE_ATTRIBUTE_READONLY);
4267         if (correct == false) {
4268                 goto out;
4269         }
4270
4271         /* Setting to (uint16_t)-1 should also be ignored. */
4272         status = cli_setpathinfo_ext(
4273                 cli,
4274                 fname,
4275                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4276                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4277                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4278                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4279                 (uint32_t)-1);
4280         if (!NT_STATUS_IS_OK(status)) {
4281                 printf("cli_setpathinfo_ext failed with %s\n",
4282                         nt_errstr(status));
4283                 correct = false;
4284         }
4285
4286         /* Check attributes are correct. */
4287         correct = check_attributes(cli,
4288                         fname,
4289                         FILE_ATTRIBUTE_SYSTEM |
4290                         FILE_ATTRIBUTE_HIDDEN |
4291                         FILE_ATTRIBUTE_READONLY);
4292         if (correct == false) {
4293                 goto out;
4294         }
4295
4296         /* Setting to 0 should clear them all. */
4297         status = cli_setpathinfo_ext(
4298                 cli,
4299                 fname,
4300                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4301                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4302                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4303                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4304                 0);
4305         if (!NT_STATUS_IS_OK(status)) {
4306                 printf("cli_setpathinfo_ext failed with %s\n",
4307                         nt_errstr(status));
4308                 correct = false;
4309         }
4310
4311         /* Check attributes are correct. */
4312         correct = check_attributes(cli,
4313                         fname,
4314                         FILE_ATTRIBUTE_NORMAL);
4315         if (correct == false) {
4316                 goto out;
4317         }
4318
4319   out:
4320
4321         cli_unlink(cli,
4322                 fname,
4323                 FILE_ATTRIBUTE_SYSTEM |
4324                 FILE_ATTRIBUTE_HIDDEN|
4325                 FILE_ATTRIBUTE_READONLY);
4326
4327         if (!torture_close_connection(cli)) {
4328                 correct = False;
4329         }
4330
4331         printf("attrib test finished\n");
4332
4333         return correct;
4334 }
4335
4336 static NTSTATUS cli_qfilename(
4337         struct cli_state *cli,
4338         uint16_t fnum,
4339         TALLOC_CTX *mem_ctx,
4340         char **_name)
4341 {
4342         uint16_t recv_flags2;
4343         uint8_t *rdata;
4344         uint32_t num_rdata;
4345         NTSTATUS status;
4346         char *name = NULL;
4347         uint32_t namelen;
4348
4349         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4350                                SMB_QUERY_FILE_NAME_INFO,
4351                                4, CLI_BUFFER_SIZE, &recv_flags2,
4352                                &rdata, &num_rdata);
4353         if (!NT_STATUS_IS_OK(status)) {
4354                 return status;
4355         }
4356
4357         namelen = IVAL(rdata, 0);
4358         if (namelen > (num_rdata - 4)) {
4359                 TALLOC_FREE(rdata);
4360                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4361         }
4362
4363         pull_string_talloc(mem_ctx,
4364                            (const char *)rdata,
4365                            recv_flags2,
4366                            &name,
4367                            rdata + 4,
4368                            namelen,
4369                            STR_UNICODE);
4370         if (name == NULL) {
4371                 status = map_nt_error_from_unix(errno);
4372                 TALLOC_FREE(rdata);
4373                 return status;
4374         }
4375
4376         *_name = name;
4377         TALLOC_FREE(rdata);
4378         return NT_STATUS_OK;
4379 }
4380
4381 /*
4382   This checks a couple of trans2 calls
4383 */
4384 static bool run_trans2test(int dummy)
4385 {
4386         struct cli_state *cli;
4387         uint16_t fnum;
4388         off_t size;
4389         time_t c_time, a_time, m_time;
4390         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4391         const char *fname = "\\trans2.tst";
4392         const char *dname = "\\trans2";
4393         const char *fname2 = "\\trans2\\trans2.tst";
4394         char *pname = NULL;
4395         bool correct = True;
4396         NTSTATUS status;
4397         uint32_t fs_attr;
4398         uint64_t ino;
4399
4400         printf("starting trans2 test\n");
4401
4402         if (!torture_open_connection(&cli, 0)) {
4403                 return False;
4404         }
4405
4406         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4407                 /* Ensure ino is zero, SMB2 gets a real one. */
4408                 ino = 0;
4409         } else {
4410                 /* Ensure ino is -1, SMB1 never gets a real one. */
4411                 ino = (uint64_t)-1;
4412         }
4413
4414         status = cli_get_fs_attr_info(cli, &fs_attr);
4415         if (!NT_STATUS_IS_OK(status)) {
4416                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4417                        nt_errstr(status));
4418                 correct = false;
4419         }
4420
4421         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4422         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4423         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4424                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4425         if (!NT_STATUS_IS_OK(status)) {
4426                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4427                 correct = False;
4428         }
4429
4430         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4431         if (!NT_STATUS_IS_OK(status)) {
4432                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4433                 correct = False;
4434         }
4435         else if (strcmp(pname, fname)) {
4436                 printf("qfilename gave different name? [%s] [%s]\n",
4437                        fname, pname);
4438                 correct = False;
4439         }
4440
4441         cli_close(cli, fnum);
4442
4443         sleep(2);
4444
4445         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4446         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4447                           &fnum);
4448         if (!NT_STATUS_IS_OK(status)) {
4449                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4450                 return False;
4451         }
4452         cli_close(cli, fnum);
4453
4454         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4455                                 NULL);
4456         if (!NT_STATUS_IS_OK(status)) {
4457                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4458                 correct = False;
4459         } else {
4460                 time_t t = time(NULL);
4461
4462                 if (c_time != m_time) {
4463                         printf("create time=%s", ctime(&c_time));
4464                         printf("modify time=%s", ctime(&m_time));
4465                         printf("This system appears to have sticky create times\n");
4466                 }
4467                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4468                         printf("access time=%s", ctime(&a_time));
4469                         printf("This system appears to set a midnight access time\n");
4470                         correct = False;
4471                 }
4472
4473                 if (labs(m_time - t) > 60*60*24*7) {
4474                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4475                         correct = False;
4476                 }
4477         }
4478
4479
4480         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4481         cli_openx(cli, fname, 
4482                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4483         cli_close(cli, fnum);
4484         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4485                                 &m_time_ts, &size, NULL, &ino);
4486         if (!NT_STATUS_IS_OK(status)) {
4487                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4488                 correct = False;
4489         } else {
4490                 if (w_time_ts.tv_sec < 60*60*24*2) {
4491                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4492                         printf("This system appears to set a initial 0 write time\n");
4493                         correct = False;
4494                 }
4495                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4496                         /* SMB2 should always return an inode. */
4497                         if (ino == 0) {
4498                                 printf("SMB2 bad inode (0)\n");
4499                                 correct = false;
4500                         }
4501                 } else {
4502                         /* SMB1 must always return zero here. */
4503                         if (ino != 0) {
4504                                 printf("SMB1 bad inode (!0)\n");
4505                                 correct = false;
4506                         }
4507                 }
4508         }
4509
4510         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4511
4512
4513         /* check if the server updates the directory modification time
4514            when creating a new file */
4515         status = cli_mkdir(cli, dname);
4516         if (!NT_STATUS_IS_OK(status)) {
4517                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4518                 correct = False;
4519         }
4520         sleep(3);
4521         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4522                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4523         if (!NT_STATUS_IS_OK(status)) {
4524                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4525                 correct = False;
4526         }
4527
4528         cli_openx(cli, fname2, 
4529                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4530         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4531         cli_close(cli, fnum);
4532         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4533                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4534         if (!NT_STATUS_IS_OK(status)) {
4535                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4536                 correct = False;
4537         } else {
4538                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4539                     == 0) {
4540                         printf("This system does not update directory modification times\n");
4541                         correct = False;
4542                 }
4543         }
4544         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4545         cli_rmdir(cli, dname);
4546
4547         if (!torture_close_connection(cli)) {
4548                 correct = False;
4549         }
4550
4551         printf("trans2 test finished\n");
4552
4553         return correct;
4554 }
4555
4556 /*
4557   This checks new W2K calls.
4558 */
4559
4560 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4561 {
4562         uint8_t *buf = NULL;
4563         uint32_t len;
4564         NTSTATUS status;
4565
4566         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4567                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4568         if (!NT_STATUS_IS_OK(status)) {
4569                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4570                        nt_errstr(status));
4571         } else {
4572                 printf("qfileinfo: level %d, len = %u\n", level, len);
4573                 dump_data(0, (uint8_t *)buf, len);
4574                 printf("\n");
4575         }
4576         TALLOC_FREE(buf);
4577         return status;
4578 }
4579
4580 static bool run_w2ktest(int dummy)
4581 {
4582         struct cli_state *cli;
4583         uint16_t fnum;
4584         const char *fname = "\\w2ktest\\w2k.tst";
4585         int level;
4586         bool correct = True;
4587
4588         printf("starting w2k test\n");
4589
4590         if (!torture_open_connection(&cli, 0)) {
4591                 return False;
4592         }
4593
4594         cli_openx(cli, fname, 
4595                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4596
4597         for (level = 1004; level < 1040; level++) {
4598                 new_trans(cli, fnum, level);
4599         }
4600
4601         cli_close(cli, fnum);
4602
4603         if (!torture_close_connection(cli)) {
4604                 correct = False;
4605         }
4606
4607         printf("w2k test finished\n");
4608
4609         return correct;
4610 }
4611
4612
4613 /*
4614   this is a harness for some oplock tests
4615  */
4616 static bool run_oplock1(int dummy)
4617 {
4618         struct cli_state *cli1;
4619         const char *fname = "\\lockt1.lck";
4620         uint16_t fnum1;
4621         bool correct = True;
4622         NTSTATUS status;
4623
4624         printf("starting oplock test 1\n");
4625
4626         if (!torture_open_connection(&cli1, 0)) {
4627                 return False;
4628         }
4629
4630         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4631
4632         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4633
4634         cli1->use_oplocks = True;
4635
4636         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4637                           &fnum1);
4638         if (!NT_STATUS_IS_OK(status)) {
4639                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4640                 return False;
4641         }
4642
4643         cli1->use_oplocks = False;
4644
4645         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4646         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4647
4648         status = cli_close(cli1, fnum1);
4649         if (!NT_STATUS_IS_OK(status)) {
4650                 printf("close2 failed (%s)\n", nt_errstr(status));
4651                 return False;
4652         }
4653
4654         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4655         if (!NT_STATUS_IS_OK(status)) {
4656                 printf("unlink failed (%s)\n", nt_errstr(status));
4657                 return False;
4658         }
4659
4660         if (!torture_close_connection(cli1)) {
4661                 correct = False;
4662         }
4663
4664         printf("finished oplock test 1\n");
4665
4666         return correct;
4667 }
4668
4669 static bool run_oplock2(int dummy)
4670 {
4671         struct cli_state *cli1, *cli2;
4672         const char *fname = "\\lockt2.lck";
4673         uint16_t fnum1, fnum2;
4674         int saved_use_oplocks = use_oplocks;
4675         char buf[4];
4676         bool correct = True;
4677         volatile bool *shared_correct;
4678         size_t nread;
4679         NTSTATUS status;
4680
4681         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4682         *shared_correct = True;
4683
4684         use_level_II_oplocks = True;
4685         use_oplocks = True;
4686
4687         printf("starting oplock test 2\n");
4688
4689         if (!torture_open_connection(&cli1, 0)) {
4690                 use_level_II_oplocks = False;
4691                 use_oplocks = saved_use_oplocks;
4692                 return False;
4693         }
4694
4695         if (!torture_open_connection(&cli2, 1)) {
4696                 use_level_II_oplocks = False;
4697                 use_oplocks = saved_use_oplocks;
4698                 return False;
4699         }
4700
4701         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4702
4703         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4704         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4705
4706         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4707                           &fnum1);
4708         if (!NT_STATUS_IS_OK(status)) {
4709                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4710                 return False;
4711         }
4712
4713         /* Don't need the globals any more. */
4714         use_level_II_oplocks = False;
4715         use_oplocks = saved_use_oplocks;
4716
4717         if (fork() == 0) {
4718                 /* Child code */
4719                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4720                 if (!NT_STATUS_IS_OK(status)) {
4721                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4722                         *shared_correct = False;
4723                         exit(0);
4724                 }
4725
4726                 sleep(2);
4727
4728                 status = cli_close(cli2, fnum2);
4729                 if (!NT_STATUS_IS_OK(status)) {
4730                         printf("close2 failed (%s)\n", nt_errstr(status));
4731                         *shared_correct = False;
4732                 }
4733
4734                 exit(0);
4735         }
4736
4737         sleep(2);
4738
4739         /* Ensure cli1 processes the break. Empty file should always return 0
4740          * bytes.  */
4741         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4742         if (!NT_STATUS_IS_OK(status)) {
4743                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4744                 correct = false;
4745         } else if (nread != 0) {
4746                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4747                       (unsigned long)nread, 0);
4748                 correct = false;
4749         }
4750
4751         /* Should now be at level II. */
4752         /* Test if sending a write locks causes a break to none. */
4753         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4754         if (!NT_STATUS_IS_OK(status)) {
4755                 printf("lock failed (%s)\n", nt_errstr(status));
4756                 correct = False;
4757         }
4758
4759         cli_unlock(cli1, fnum1, 0, 4);
4760
4761         sleep(2);
4762
4763         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4764         if (!NT_STATUS_IS_OK(status)) {
4765                 printf("lock failed (%s)\n", nt_errstr(status));
4766                 correct = False;
4767         }
4768
4769         cli_unlock(cli1, fnum1, 0, 4);
4770
4771         sleep(2);
4772
4773         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4774
4775         status = cli_close(cli1, fnum1);
4776         if (!NT_STATUS_IS_OK(status)) {
4777                 printf("close1 failed (%s)\n", nt_errstr(status));
4778                 correct = False;
4779         }
4780
4781         sleep(4);
4782
4783         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4784         if (!NT_STATUS_IS_OK(status)) {
4785                 printf("unlink failed (%s)\n", nt_errstr(status));
4786                 correct = False;
4787         }
4788
4789         if (!torture_close_connection(cli1)) {
4790                 correct = False;
4791         }
4792
4793         if (!*shared_correct) {
4794                 correct = False;
4795         }
4796
4797         printf("finished oplock test 2\n");
4798
4799         return correct;
4800 }
4801
4802 struct oplock4_state {
4803         struct tevent_context *ev;
4804         struct cli_state *cli;
4805         bool *got_break;
4806         uint16_t *fnum2;
4807 };
4808
4809 static void oplock4_got_break(struct tevent_req *req);
4810 static void oplock4_got_open(struct tevent_req *req);
4811
4812 static bool run_oplock4(int dummy)
4813 {
4814         struct tevent_context *ev;
4815         struct cli_state *cli1, *cli2;
4816         struct tevent_req *oplock_req, *open_req;
4817         const char *fname = "\\lockt4.lck";
4818         const char *fname_ln = "\\lockt4_ln.lck";
4819         uint16_t fnum1, fnum2;
4820         int saved_use_oplocks = use_oplocks;
4821         NTSTATUS status;
4822         bool correct = true;
4823
4824         bool got_break;
4825
4826         struct oplock4_state *state;
4827
4828         printf("starting oplock test 4\n");
4829
4830         if (!torture_open_connection(&cli1, 0)) {
4831                 use_level_II_oplocks = false;
4832                 use_oplocks = saved_use_oplocks;
4833                 return false;
4834         }
4835
4836         if (!torture_open_connection(&cli2, 1)) {
4837                 use_level_II_oplocks = false;
4838                 use_oplocks = saved_use_oplocks;
4839                 return false;
4840         }
4841
4842         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4843         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4844
4845         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4846         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4847
4848         /* Create the file. */
4849         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4850                           &fnum1);
4851         if (!NT_STATUS_IS_OK(status)) {
4852                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4853                 return false;
4854         }
4855
4856         status = cli_close(cli1, fnum1);
4857         if (!NT_STATUS_IS_OK(status)) {
4858                 printf("close1 failed (%s)\n", nt_errstr(status));
4859                 return false;
4860         }
4861
4862         /* Now create a hardlink. */
4863         status = cli_hardlink(cli1, fname, fname_ln);
4864         if (!NT_STATUS_IS_OK(status)) {
4865                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4866                 return false;
4867         }
4868
4869         /* Prove that opening hardlinks cause deny modes to conflict. */
4870         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4871         if (!NT_STATUS_IS_OK(status)) {
4872                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4873                 return false;
4874         }
4875
4876         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4877         if (NT_STATUS_IS_OK(status)) {
4878                 printf("open of %s succeeded - should fail with sharing violation.\n",
4879                         fname_ln);
4880                 return false;
4881         }
4882
4883         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4884                 printf("open of %s should fail with sharing violation. Got %s\n",
4885                         fname_ln, nt_errstr(status));
4886                 return false;
4887         }
4888
4889         status = cli_close(cli1, fnum1);
4890         if (!NT_STATUS_IS_OK(status)) {
4891                 printf("close1 failed (%s)\n", nt_errstr(status));
4892                 return false;
4893         }
4894
4895         cli1->use_oplocks = true;
4896         cli2->use_oplocks = true;
4897
4898         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4899         if (!NT_STATUS_IS_OK(status)) {
4900                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4901                 return false;
4902         }
4903
4904         ev = samba_tevent_context_init(talloc_tos());
4905         if (ev == NULL) {
4906                 printf("tevent_context_init failed\n");
4907                 return false;
4908         }
4909
4910         state = talloc(ev, struct oplock4_state);
4911         if (state == NULL) {
4912                 printf("talloc failed\n");
4913                 return false;
4914         }
4915         state->ev = ev;
4916         state->cli = cli1;
4917         state->got_break = &got_break;
4918         state->fnum2 = &fnum2;
4919
4920         oplock_req = cli_smb_oplock_break_waiter_send(
4921                 talloc_tos(), ev, cli1);
4922         if (oplock_req == NULL) {
4923                 printf("cli_smb_oplock_break_waiter_send failed\n");
4924                 return false;
4925         }
4926         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4927
4928         open_req = cli_openx_send(
4929                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4930         if (open_req == NULL) {
4931                 printf("cli_openx_send failed\n");
4932                 return false;
4933         }
4934         tevent_req_set_callback(open_req, oplock4_got_open, state);
4935
4936         got_break = false;
4937         fnum2 = 0xffff;
4938
4939         while (!got_break || fnum2 == 0xffff) {
4940                 int ret;
4941                 ret = tevent_loop_once(ev);
4942                 if (ret == -1) {
4943                         printf("tevent_loop_once failed: %s\n",
4944                                strerror(errno));
4945                         return false;
4946                 }
4947         }
4948
4949         status = cli_close(cli2, fnum2);
4950         if (!NT_STATUS_IS_OK(status)) {
4951                 printf("close2 failed (%s)\n", nt_errstr(status));
4952                 correct = false;
4953         }
4954
4955         status = cli_close(cli1, fnum1);
4956         if (!NT_STATUS_IS_OK(status)) {
4957                 printf("close1 failed (%s)\n", nt_errstr(status));
4958                 correct = false;
4959         }
4960
4961         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4962         if (!NT_STATUS_IS_OK(status)) {
4963                 printf("unlink failed (%s)\n", nt_errstr(status));
4964                 correct = false;
4965         }
4966
4967         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4968         if (!NT_STATUS_IS_OK(status)) {
4969                 printf("unlink failed (%s)\n", nt_errstr(status));
4970                 correct = false;
4971         }
4972
4973         if (!torture_close_connection(cli1)) {
4974                 correct = false;
4975         }
4976
4977         if (!got_break) {
4978                 correct = false;
4979         }
4980
4981         printf("finished oplock test 4\n");
4982
4983         return correct;
4984 }
4985
4986 static void oplock4_got_break(struct tevent_req *req)
4987 {
4988         struct oplock4_state *state = tevent_req_callback_data(
4989                 req, struct oplock4_state);
4990         uint16_t fnum;
4991         uint8_t level;
4992         NTSTATUS status;
4993
4994         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4995         TALLOC_FREE(req);
4996         if (!NT_STATUS_IS_OK(status)) {
4997                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4998                        nt_errstr(status));
4999                 return;
5000         }
5001         *state->got_break = true;
5002
5003         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5004                                   NO_OPLOCK);
5005         if (req == NULL) {
5006                 printf("cli_oplock_ack_send failed\n");
5007                 return;
5008         }
5009 }
5010
5011 static void oplock4_got_open(struct tevent_req *req)
5012 {
5013         struct oplock4_state *state = tevent_req_callback_data(
5014                 req, struct oplock4_state);
5015         NTSTATUS status;
5016
5017         status = cli_openx_recv(req, state->fnum2);
5018         if (!NT_STATUS_IS_OK(status)) {
5019                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5020                 *state->fnum2 = 0xffff;
5021         }
5022 }
5023
5024 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5025
5026 struct oplock5_state {
5027         int pipe_down_fd;
5028 };
5029
5030 /*
5031  * Async open the file that has a kernel oplock, do an echo to get
5032  * that 100% across, close the file to signal to the child fd that the
5033  * oplock can be dropped, wait for the open reply.
5034  */
5035
5036 static void oplock5_opened(struct tevent_req *subreq);
5037 static void oplock5_pong(struct tevent_req *subreq);
5038 static void oplock5_timedout(struct tevent_req *subreq);
5039
5040 static struct tevent_req *oplock5_send(
5041         TALLOC_CTX *mem_ctx,
5042         struct tevent_context *ev,
5043         struct cli_state *cli,
5044         const char *fname,
5045         int pipe_down_fd)
5046 {
5047         struct tevent_req *req = NULL, *subreq = NULL;
5048         struct oplock5_state *state = NULL;
5049         static uint8_t data = 0;
5050
5051         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5052         if (req == NULL) {
5053                 return NULL;
5054         }
5055         state->pipe_down_fd = pipe_down_fd;
5056
5057         subreq = cli_ntcreate_send(
5058                 state,
5059                 ev,
5060                 cli,
5061                 fname,
5062                 0,                      /* CreatFlags */
5063                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5064                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5065                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5066                 FILE_OPEN,               /* CreateDisposition */
5067                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5068                 0,                       /* Impersonation */
5069                 0);                      /* SecurityFlags */
5070         if (tevent_req_nomem(subreq, req)) {
5071                 return tevent_req_post(req, ev);
5072         }
5073         tevent_req_set_callback(subreq, oplock5_opened, req);
5074
5075         subreq = cli_echo_send(
5076                 state,
5077                 ev,
5078                 cli,
5079                 1,
5080                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5081         if (tevent_req_nomem(subreq, req)) {
5082                 return tevent_req_post(req, ev);
5083         }
5084         tevent_req_set_callback(subreq, oplock5_pong, req);
5085
5086         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5087         if (tevent_req_nomem(subreq, req)) {
5088                 return tevent_req_post(req, ev);
5089         }
5090         tevent_req_set_callback(subreq, oplock5_timedout, req);
5091
5092         return req;
5093 }
5094
5095 static void oplock5_opened(struct tevent_req *subreq)
5096 {
5097         struct tevent_req *req = tevent_req_callback_data(
5098                 subreq, struct tevent_req);
5099         NTSTATUS status;
5100         uint16_t fnum;
5101
5102         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5103         TALLOC_FREE(subreq);
5104         if (tevent_req_nterror(req, status)) {
5105                 return;
5106         }
5107         tevent_req_done(req);
5108 }
5109
5110 static void oplock5_pong(struct tevent_req *subreq)
5111 {
5112         struct tevent_req *req = tevent_req_callback_data(
5113                 subreq, struct tevent_req);
5114         struct oplock5_state *state = tevent_req_data(
5115                 req, struct oplock5_state);
5116         NTSTATUS status;
5117
5118         status = cli_echo_recv(subreq);
5119         TALLOC_FREE(subreq);
5120         if (tevent_req_nterror(req, status)) {
5121                 return;
5122         }
5123
5124         close(state->pipe_down_fd);
5125 }
5126
5127 static void oplock5_timedout(struct tevent_req *subreq)
5128 {
5129         struct tevent_req *req = tevent_req_callback_data(
5130                 subreq, struct tevent_req);
5131         bool ok;
5132
5133         ok = tevent_wakeup_recv(subreq);
5134         TALLOC_FREE(subreq);
5135         if (!ok) {
5136                 tevent_req_oom(req);
5137                 return;
5138         }
5139         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5140 }
5141
5142 static NTSTATUS oplock5_recv(struct tevent_req *req)
5143 {
5144         return tevent_req_simple_recv_ntstatus(req);
5145 }
5146
5147 static bool run_oplock5(int dummy)
5148 {
5149         struct tevent_context *ev = NULL;
5150         struct tevent_req *req = NULL;
5151         struct cli_state *cli = NULL;
5152         const char *fname = "oplock5.txt";
5153         int pipe_down[2], pipe_up[2];
5154         pid_t child_pid;
5155         uint8_t c = '\0';
5156         NTSTATUS status;
5157         int ret;
5158         bool ok;
5159
5160         printf("starting oplock5\n");
5161
5162         if (local_path == NULL) {
5163                 d_fprintf(stderr, "oplock5 must be given a local path via "
5164                           "-l <localpath>\n");
5165                 return false;
5166         }
5167
5168         ret = pipe(pipe_down);
5169         if (ret == -1) {
5170                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5171                 return false;
5172         }
5173         ret = pipe(pipe_up);
5174         if (ret == -1) {
5175                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5176                 return false;
5177         }
5178
5179         child_pid = fork();
5180         if (child_pid == -1) {
5181                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5182                 return false;
5183         }
5184
5185         if (child_pid == 0) {
5186                 char *local_file = NULL;
5187                 int fd;
5188
5189                 close(pipe_down[1]);
5190                 close(pipe_up[0]);
5191
5192                 local_file = talloc_asprintf(
5193                         talloc_tos(), "%s/%s", local_path, fname);
5194                 if (local_file == 0) {
5195                         c = 1;
5196                         goto do_write;
5197                 }
5198                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5199                 if (fd == -1) {
5200                         d_fprintf(stderr,
5201                                   "open(%s) in child failed: %s\n",
5202                                   local_file,
5203                                   strerror(errno));
5204                         c = 2;
5205                         goto do_write;
5206                 }
5207
5208                 signal(SIGIO, SIG_IGN);
5209
5210                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5211                 if (ret == -1) {
5212                         d_fprintf(stderr,
5213                                   "SETLEASE in child failed: %s\n",
5214                                   strerror(errno));
5215                         c = 3;
5216                         goto do_write;
5217                 }
5218
5219         do_write:
5220                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5221                 if (ret == -1) {
5222                         d_fprintf(stderr,
5223                                   "sys_write failed: %s\n",
5224                                   strerror(errno));
5225                         exit(4);
5226                 }
5227                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5228                 if (ret == -1) {
5229                         d_fprintf(stderr,
5230                                   "sys_read failed: %s\n",
5231                                   strerror(errno));
5232                         exit(5);
5233                 }
5234                 exit(0);
5235         }
5236
5237         close(pipe_up[1]);
5238         close(pipe_down[0]);
5239
5240         ret = sys_read(pipe_up[0], &c, sizeof(c));
5241         if (ret != 1) {
5242                 d_fprintf(stderr,
5243                           "sys_read failed: %s\n",
5244                           strerror(errno));
5245                 return false;
5246         }
5247         if (c != 0) {
5248                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5249                 return false;
5250         }
5251
5252         ok = torture_open_connection(&cli, 0);
5253         if (!ok) {
5254                 d_fprintf(stderr, "torture_open_connection failed\n");
5255                 return false;
5256         }
5257
5258         ev = samba_tevent_context_init(talloc_tos());
5259         if (ev == NULL) {
5260                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5261                 return false;
5262         }
5263
5264         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5265         if (req == NULL) {
5266                 d_fprintf(stderr, "oplock5_send failed\n");
5267                 return false;
5268         }
5269
5270         ok = tevent_req_poll_ntstatus(req, ev, &status);
5271         if (!ok) {
5272                 d_fprintf(stderr,
5273                           "tevent_req_poll_ntstatus failed: %s\n",
5274                           nt_errstr(status));
5275                 return false;
5276         }
5277
5278         status = oplock5_recv(req);
5279         TALLOC_FREE(req);
5280         if (!NT_STATUS_IS_OK(status)) {
5281                 d_fprintf(stderr,
5282                           "oplock5 failed: %s\n",
5283                           nt_errstr(status));
5284                 return false;
5285         }
5286
5287         return true;
5288 }
5289
5290 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5291
5292 /*
5293   Test delete on close semantics.
5294  */
5295 static bool run_deletetest(int dummy)
5296 {
5297         struct cli_state *cli1 = NULL;
5298         struct cli_state *cli2 = NULL;
5299         const char *fname = "\\delete.file";
5300         uint16_t fnum1 = (uint16_t)-1;
5301         uint16_t fnum2 = (uint16_t)-1;
5302         bool correct = false;
5303         NTSTATUS status;
5304
5305         printf("starting delete test\n");
5306
5307         if (!torture_open_connection(&cli1, 0)) {
5308                 return False;
5309         }
5310
5311         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5312
5313         /* Test 1 - this should delete the file on close. */
5314
5315         cli_setatr(cli1, fname, 0, 0);
5316         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5317
5318         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5319                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5320                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5321         if (!NT_STATUS_IS_OK(status)) {
5322                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5323                 goto fail;
5324         }
5325
5326         status = cli_close(cli1, fnum1);
5327         if (!NT_STATUS_IS_OK(status)) {
5328                 printf("[1] close failed (%s)\n", nt_errstr(status));
5329                 goto fail;
5330         }
5331
5332         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5333         if (NT_STATUS_IS_OK(status)) {
5334                 printf("[1] open of %s succeeded (should fail)\n", fname);
5335                 goto fail;
5336         }
5337
5338         printf("first delete on close test succeeded.\n");
5339
5340         /* Test 2 - this should delete the file on close. */
5341
5342         cli_setatr(cli1, fname, 0, 0);
5343         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5344
5345         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5346                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5347                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5348         if (!NT_STATUS_IS_OK(status)) {
5349                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5350                 goto fail;
5351         }
5352
5353         status = cli_nt_delete_on_close(cli1, fnum1, true);
5354         if (!NT_STATUS_IS_OK(status)) {
5355                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5356                 goto fail;
5357         }
5358
5359         status = cli_close(cli1, fnum1);
5360         if (!NT_STATUS_IS_OK(status)) {
5361                 printf("[2] close failed (%s)\n", nt_errstr(status));
5362                 goto fail;
5363         }
5364
5365         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5366         if (NT_STATUS_IS_OK(status)) {
5367                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5368                 status = cli_close(cli1, fnum1);
5369                 if (!NT_STATUS_IS_OK(status)) {
5370                         printf("[2] close failed (%s)\n", nt_errstr(status));
5371                 }
5372                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5373                 goto fail;
5374         }
5375
5376         printf("second delete on close test succeeded.\n");
5377
5378         /* Test 3 - ... */
5379         cli_setatr(cli1, fname, 0, 0);
5380         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5381
5382         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5383                               FILE_ATTRIBUTE_NORMAL,
5384                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5385                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5386         if (!NT_STATUS_IS_OK(status)) {
5387                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5388                 goto fail;
5389         }
5390
5391         /* This should fail with a sharing violation - open for delete is only compatible
5392            with SHARE_DELETE. */
5393
5394         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5395                               FILE_ATTRIBUTE_NORMAL,
5396                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5397                               FILE_OPEN, 0, 0, &fnum2, NULL);
5398         if (NT_STATUS_IS_OK(status)) {
5399                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5400                 goto fail;
5401         }
5402
5403         /* This should succeed. */
5404         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5405                              FILE_ATTRIBUTE_NORMAL,
5406                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5407                              FILE_OPEN, 0, 0, &fnum2, NULL);
5408         if (!NT_STATUS_IS_OK(status)) {
5409                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5410                 goto fail;
5411         }
5412
5413         status = cli_nt_delete_on_close(cli1, fnum1, true);
5414         if (!NT_STATUS_IS_OK(status)) {
5415                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5416                 goto fail;
5417         }
5418
5419         status = cli_close(cli1, fnum1);
5420         if (!NT_STATUS_IS_OK(status)) {
5421                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5422                 goto fail;
5423         }
5424
5425         status = cli_close(cli1, fnum2);
5426         if (!NT_STATUS_IS_OK(status)) {
5427                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5428                 goto fail;
5429         }
5430
5431         /* This should fail - file should no longer be there. */
5432
5433         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5434         if (NT_STATUS_IS_OK(status)) {
5435                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5436                 status = cli_close(cli1, fnum1);
5437                 if (!NT_STATUS_IS_OK(status)) {
5438                         printf("[3] close failed (%s)\n", nt_errstr(status));
5439                 }
5440                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5441                 goto fail;
5442         }
5443
5444         printf("third delete on close test succeeded.\n");
5445
5446         /* Test 4 ... */
5447         cli_setatr(cli1, fname, 0, 0);
5448         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5449
5450         status = cli_ntcreate(cli1, fname, 0,
5451                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5452                               FILE_ATTRIBUTE_NORMAL,
5453                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5454                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5455         if (!NT_STATUS_IS_OK(status)) {
5456                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5457                 goto fail;
5458         }
5459
5460         /* This should succeed. */
5461         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5462                              FILE_ATTRIBUTE_NORMAL,
5463                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5464                              FILE_OPEN, 0, 0, &fnum2, NULL);
5465         if (!NT_STATUS_IS_OK(status)) {
5466                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5467                 goto fail;
5468         }
5469
5470         status = cli_close(cli1, fnum2);
5471         if (!NT_STATUS_IS_OK(status)) {
5472                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5473                 goto fail;
5474         }
5475
5476         status = cli_nt_delete_on_close(cli1, fnum1, true);
5477         if (!NT_STATUS_IS_OK(status)) {
5478                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5479                 goto fail;
5480         }
5481
5482         /* This should fail - no more opens once delete on close set. */
5483         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5484                               FILE_ATTRIBUTE_NORMAL,
5485                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5486                               FILE_OPEN, 0, 0, &fnum2, NULL);
5487         if (NT_STATUS_IS_OK(status)) {
5488                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5489                 goto fail;
5490         }
5491
5492         status = cli_close(cli1, fnum1);
5493         if (!NT_STATUS_IS_OK(status)) {
5494                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5495                 goto fail;
5496         }
5497
5498         printf("fourth delete on close test succeeded.\n");
5499
5500         /* Test 5 ... */
5501         cli_setatr(cli1, fname, 0, 0);
5502         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5503
5504         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5505         if (!NT_STATUS_IS_OK(status)) {
5506                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5507                 goto fail;
5508         }
5509
5510         /* This should fail - only allowed on NT opens with DELETE access. */
5511
5512         status = cli_nt_delete_on_close(cli1, fnum1, true);
5513         if (NT_STATUS_IS_OK(status)) {
5514                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5515                 goto fail;
5516         }
5517
5518         status = cli_close(cli1, fnum1);
5519         if (!NT_STATUS_IS_OK(status)) {
5520                 printf("[5] close failed (%s)\n", nt_errstr(status));
5521                 goto fail;
5522         }
5523
5524         printf("fifth delete on close test succeeded.\n");
5525
5526         /* Test 6 ... */
5527         cli_setatr(cli1, fname, 0, 0);
5528         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5529
5530         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5531                              FILE_ATTRIBUTE_NORMAL,
5532                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5533                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5534         if (!NT_STATUS_IS_OK(status)) {
5535                 printf("[6] open of %s failed (%s)\n", fname,
5536                        nt_errstr(status));
5537                 goto fail;
5538         }
5539
5540         /* This should fail - only allowed on NT opens with DELETE access. */
5541
5542         status = cli_nt_delete_on_close(cli1, fnum1, true);
5543         if (NT_STATUS_IS_OK(status)) {
5544                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5545                 goto fail;
5546         }
5547
5548         status = cli_close(cli1, fnum1);
5549         if (!NT_STATUS_IS_OK(status)) {
5550                 printf("[6] close failed (%s)\n", nt_errstr(status));
5551                 goto fail;
5552         }
5553
5554         printf("sixth delete on close test succeeded.\n");
5555
5556         /* Test 7 ... */
5557         cli_setatr(cli1, fname, 0, 0);
5558         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5559
5560         status = cli_ntcreate(cli1, fname, 0,
5561                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5562                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5563                               0, 0, &fnum1, NULL);
5564         if (!NT_STATUS_IS_OK(status)) {
5565                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5566                 goto fail;
5567         }
5568
5569         status = cli_nt_delete_on_close(cli1, fnum1, true);
5570         if (!NT_STATUS_IS_OK(status)) {
5571                 printf("[7] setting delete_on_close on file failed !\n");
5572                 goto fail;
5573         }
5574
5575         status = cli_nt_delete_on_close(cli1, fnum1, false);
5576         if (!NT_STATUS_IS_OK(status)) {
5577                 printf("[7] unsetting delete_on_close on file failed !\n");
5578                 goto fail;
5579         }
5580
5581         status = cli_close(cli1, fnum1);
5582         if (!NT_STATUS_IS_OK(status)) {
5583                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5584                 goto fail;
5585         }
5586
5587         /* This next open should succeed - we reset the flag. */
5588         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5589         if (!NT_STATUS_IS_OK(status)) {
5590                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5591                 goto fail;
5592         }
5593
5594         status = cli_close(cli1, fnum1);
5595         if (!NT_STATUS_IS_OK(status)) {
5596                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5597                 goto fail;
5598         }
5599
5600         printf("seventh delete on close test succeeded.\n");
5601
5602         /* Test 8 ... */
5603         cli_setatr(cli1, fname, 0, 0);
5604         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5605
5606         if (!torture_open_connection(&cli2, 1)) {
5607                 printf("[8] failed to open second connection.\n");
5608                 goto fail;
5609         }
5610
5611         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5612
5613         status = cli_ntcreate(cli1, fname, 0,
5614                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5615                              FILE_ATTRIBUTE_NORMAL,
5616                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5617                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5618         if (!NT_STATUS_IS_OK(status)) {
5619                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5620                 goto fail;
5621         }
5622
5623         status = cli_ntcreate(cli2, fname, 0,
5624                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5625                              FILE_ATTRIBUTE_NORMAL,
5626                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627                              FILE_OPEN, 0, 0, &fnum2, NULL);
5628         if (!NT_STATUS_IS_OK(status)) {
5629                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5630                 goto fail;
5631         }
5632
5633         status = cli_nt_delete_on_close(cli1, fnum1, true);
5634         if (!NT_STATUS_IS_OK(status)) {
5635                 printf("[8] setting delete_on_close on file failed !\n");
5636                 goto fail;
5637         }
5638
5639         status = cli_close(cli1, fnum1);
5640         if (!NT_STATUS_IS_OK(status)) {
5641                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5642                 goto fail;
5643         }
5644
5645         status = cli_close(cli2, fnum2);
5646         if (!NT_STATUS_IS_OK(status)) {
5647                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5648                 goto fail;
5649         }
5650
5651         /* This should fail.. */
5652         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5653         if (NT_STATUS_IS_OK(status)) {
5654                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5655                 goto fail;
5656         }
5657
5658         printf("eighth delete on close test succeeded.\n");
5659
5660         /* Test 9 ... */
5661
5662         /* This should fail - we need to set DELETE_ACCESS. */
5663         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5664                               FILE_ATTRIBUTE_NORMAL,
5665                               FILE_SHARE_NONE,
5666                               FILE_OVERWRITE_IF,
5667                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5668         if (NT_STATUS_IS_OK(status)) {
5669                 printf("[9] open of %s succeeded should have failed!\n", fname);
5670                 goto fail;
5671         }
5672
5673         printf("ninth delete on close test succeeded.\n");
5674
5675         /* Test 10 ... */
5676
5677         status = cli_ntcreate(cli1, fname, 0,
5678                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5679                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5680                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5681                              0, &fnum1, NULL);
5682         if (!NT_STATUS_IS_OK(status)) {
5683                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5684                 goto fail;
5685         }
5686
5687         /* This should delete the file. */
5688         status = cli_close(cli1, fnum1);
5689         if (!NT_STATUS_IS_OK(status)) {
5690                 printf("[10] close failed (%s)\n", nt_errstr(status));
5691                 goto fail;
5692         }
5693
5694         /* This should fail.. */
5695         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5696         if (NT_STATUS_IS_OK(status)) {
5697                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5698                 goto fail;
5699         }
5700
5701         printf("tenth delete on close test succeeded.\n");
5702
5703         /* Test 11 ... */
5704
5705         cli_setatr(cli1, fname, 0, 0);
5706         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5707
5708         /* Can we open a read-only file with delete access? */
5709
5710         /* Create a readonly file. */
5711         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5712                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5713                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5714         if (!NT_STATUS_IS_OK(status)) {
5715                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5716                 goto fail;
5717         }
5718
5719         status = cli_close(cli1, fnum1);
5720         if (!NT_STATUS_IS_OK(status)) {
5721                 printf("[11] close failed (%s)\n", nt_errstr(status));
5722                 goto fail;
5723         }
5724
5725         /* Now try open for delete access. */
5726         status = cli_ntcreate(cli1, fname, 0,
5727                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5728                              0,
5729                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5730                              FILE_OPEN, 0, 0, &fnum1, NULL);
5731         if (!NT_STATUS_IS_OK(status)) {
5732                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5733                 goto fail;
5734         }
5735
5736         cli_close(cli1, fnum1);
5737
5738         printf("eleventh delete on close test succeeded.\n");
5739
5740         /*
5741          * Test 12
5742          * like test 4 but with initial delete on close
5743          */
5744
5745         cli_setatr(cli1, fname, 0, 0);
5746         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5747
5748         status = cli_ntcreate(cli1, fname, 0,
5749                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5750                               FILE_ATTRIBUTE_NORMAL,
5751                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5752                               FILE_OVERWRITE_IF,
5753                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5754         if (!NT_STATUS_IS_OK(status)) {
5755                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5756                 goto fail;
5757         }
5758
5759         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5760                               FILE_ATTRIBUTE_NORMAL,
5761                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5762                               FILE_OPEN, 0, 0, &fnum2, NULL);
5763         if (!NT_STATUS_IS_OK(status)) {
5764                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5765                 goto fail;
5766         }
5767
5768         status = cli_close(cli1, fnum2);
5769         if (!NT_STATUS_IS_OK(status)) {
5770                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5771                 goto fail;
5772         }
5773
5774         status = cli_nt_delete_on_close(cli1, fnum1, true);
5775         if (!NT_STATUS_IS_OK(status)) {
5776                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5777                 goto fail;
5778         }
5779
5780         /* This should fail - no more opens once delete on close set. */
5781         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5782                               FILE_ATTRIBUTE_NORMAL,
5783                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5784                               FILE_OPEN, 0, 0, &fnum2, NULL);
5785         if (NT_STATUS_IS_OK(status)) {
5786                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5787                 goto fail;
5788         }
5789
5790         status = cli_nt_delete_on_close(cli1, fnum1, false);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5793                 goto fail;
5794         }
5795
5796         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5797                               FILE_ATTRIBUTE_NORMAL,
5798                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5799                               FILE_OPEN, 0, 0, &fnum2, NULL);
5800         if (!NT_STATUS_IS_OK(status)) {
5801                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5802                 goto fail;
5803         }
5804
5805         status = cli_close(cli1, fnum2);
5806         if (!NT_STATUS_IS_OK(status)) {
5807                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5808                 goto fail;
5809         }
5810
5811         status = cli_close(cli1, fnum1);
5812         if (!NT_STATUS_IS_OK(status)) {
5813                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5814                 goto fail;
5815         }
5816
5817         /*
5818          * setting delete on close on the handle does
5819          * not unset the initial delete on close...
5820          */
5821         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5822                               FILE_ATTRIBUTE_NORMAL,
5823                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5824                               FILE_OPEN, 0, 0, &fnum2, NULL);
5825         if (NT_STATUS_IS_OK(status)) {
5826                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5827                 goto fail;
5828         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5829                 printf("ntcreate returned %s, expected "
5830                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5831                        nt_errstr(status));
5832                 goto fail;
5833         }
5834
5835         printf("twelfth delete on close test succeeded.\n");
5836
5837
5838         printf("finished delete test\n");
5839
5840         correct = true;
5841
5842   fail:
5843         /* FIXME: This will crash if we aborted before cli2 got
5844          * intialized, because these functions don't handle
5845          * uninitialized connections. */
5846
5847         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5848         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5849         cli_setatr(cli1, fname, 0, 0);
5850         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5851
5852         if (cli1 && !torture_close_connection(cli1)) {
5853                 correct = False;
5854         }
5855         if (cli2 && !torture_close_connection(cli2)) {
5856                 correct = False;
5857         }
5858         return correct;
5859 }
5860
5861 struct delete_stream_state {
5862         bool closed;
5863 };
5864
5865 static void delete_stream_unlinked(struct tevent_req *subreq);
5866 static void delete_stream_closed(struct tevent_req *subreq);
5867
5868 static struct tevent_req *delete_stream_send(
5869         TALLOC_CTX *mem_ctx,
5870         struct tevent_context *ev,
5871         struct cli_state *cli,
5872         const char *base_fname,
5873         uint16_t stream_fnum)
5874 {
5875         struct tevent_req *req = NULL, *subreq = NULL;
5876         struct delete_stream_state *state = NULL;
5877
5878         req = tevent_req_create(
5879                 mem_ctx, &state, struct delete_stream_state);
5880         if (req == NULL) {
5881                 return NULL;
5882         }
5883
5884         subreq = cli_unlink_send(
5885                 state,
5886                 ev,
5887                 cli,
5888                 base_fname,
5889                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5890         if (tevent_req_nomem(subreq, req)) {
5891                 return tevent_req_post(req, ev);
5892         }
5893         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5894
5895         subreq = cli_close_send(state, ev, cli, stream_fnum);
5896         if (tevent_req_nomem(subreq, req)) {
5897                 return tevent_req_post(req, ev);
5898         }
5899         tevent_req_set_callback(subreq, delete_stream_closed, req);
5900
5901         return req;
5902 }
5903
5904 static void delete_stream_unlinked(struct tevent_req *subreq)
5905 {
5906         struct tevent_req *req = tevent_req_callback_data(
5907                 subreq, struct tevent_req);
5908         struct delete_stream_state *state = tevent_req_data(
5909                 req, struct delete_stream_state);
5910         NTSTATUS status;
5911
5912         status = cli_unlink_recv(subreq);
5913         TALLOC_FREE(subreq);
5914         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5915                 printf("cli_unlink returned %s\n",
5916                        nt_errstr(status));
5917                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5918                 return;
5919         }
5920         if (!state->closed) {
5921                 /* close reply should have come in first */
5922                 printf("Not closed\n");
5923                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5924                 return;
5925         }
5926         tevent_req_done(req);
5927 }
5928
5929 static void delete_stream_closed(struct tevent_req *subreq)
5930 {
5931         struct tevent_req *req = tevent_req_callback_data(
5932                 subreq, struct tevent_req);
5933         struct delete_stream_state *state = tevent_req_data(
5934                 req, struct delete_stream_state);
5935         NTSTATUS status;
5936
5937         status = cli_close_recv(subreq);
5938         TALLOC_FREE(subreq);
5939         if (tevent_req_nterror(req, status)) {
5940                 return;
5941         }
5942         /* also waiting for the unlink to come back */
5943         state->closed = true;
5944 }
5945
5946 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5947 {
5948         return tevent_req_simple_recv_ntstatus(req);
5949 }
5950
5951 static bool run_delete_stream(int dummy)
5952 {
5953         struct tevent_context *ev = NULL;
5954         struct tevent_req *req = NULL;
5955         struct cli_state *cli = NULL;
5956         const char fname[] = "delete_stream";
5957         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5958         uint16_t fnum1, fnum2;
5959         NTSTATUS status;
5960         bool ok;
5961
5962         printf("Starting stream delete test\n");
5963
5964         ok = torture_open_connection(&cli, 0);
5965         if (!ok) {
5966                 return false;
5967         }
5968
5969         cli_setatr(cli, fname, 0, 0);
5970         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5971
5972         /* Create the file. */
5973         status = cli_ntcreate(
5974                 cli,
5975                 fname,
5976                 0,
5977                 READ_CONTROL_ACCESS,
5978                 0,
5979                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5980                 FILE_CREATE,
5981                 0x0,
5982                 0x0,
5983                 &fnum1,
5984                 NULL);
5985         if (!NT_STATUS_IS_OK(status)) {
5986                 d_fprintf(stderr,
5987                           "cli_ntcreate of %s failed (%s)\n",
5988                           fname,
5989                           nt_errstr(status));
5990                 return false;
5991         }
5992         status = cli_close(cli, fnum1);
5993         if (!NT_STATUS_IS_OK(status)) {
5994                 d_fprintf(stderr,
5995                           "cli_close of %s failed (%s)\n",
5996                           fname,
5997                           nt_errstr(status));
5998                 return false;
5999         }
6000
6001         /* Now create the stream. */
6002         status = cli_ntcreate(
6003                 cli,
6004                 fname_stream,
6005                 0,
6006                 FILE_WRITE_DATA,
6007                 0,
6008                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6009                 FILE_CREATE,
6010                 0x0,
6011                 0x0,
6012                 &fnum1,
6013                 NULL);
6014
6015         if (!NT_STATUS_IS_OK(status)) {
6016                 d_fprintf(stderr,
6017                           "cli_ntcreate of %s failed (%s)\n",
6018                           fname_stream,
6019                           nt_errstr(status));
6020                 return false;
6021         }
6022
6023         /* open it a second time */
6024
6025         status = cli_ntcreate(
6026                 cli,
6027                 fname_stream,
6028                 0,
6029                 FILE_WRITE_DATA,
6030                 0,
6031                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6032                 FILE_OPEN,
6033                 0x0,
6034                 0x0,
6035                 &fnum2,
6036                 NULL);
6037
6038         if (!NT_STATUS_IS_OK(status)) {
6039                 d_fprintf(stderr,
6040                           "2nd cli_ntcreate of %s failed (%s)\n",
6041                           fname_stream,
6042                           nt_errstr(status));
6043                 return false;
6044         }
6045
6046         ev = samba_tevent_context_init(talloc_tos());
6047         if (ev == NULL) {
6048                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6049                 return false;
6050         }
6051
6052         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6053         if (req == NULL) {
6054                 d_fprintf(stderr, "delete_stream_send failed\n");
6055                 return false;
6056         }
6057
6058         ok = tevent_req_poll_ntstatus(req, ev, &status);
6059         if (!ok) {
6060                 d_fprintf(stderr,
6061                           "tevent_req_poll_ntstatus failed: %s\n",
6062                           nt_errstr(status));
6063                 return false;
6064         }
6065
6066         status = delete_stream_recv(req);
6067         TALLOC_FREE(req);
6068         if (!NT_STATUS_IS_OK(status)) {
6069                 d_fprintf(stderr,
6070                           "delete_stream failed: %s\n",
6071                           nt_errstr(status));
6072                 return false;
6073         }
6074
6075         status = cli_close(cli, fnum2);
6076         if (!NT_STATUS_IS_OK(status)) {
6077                 d_fprintf(stderr,
6078                           "close failed: %s\n",
6079                           nt_errstr(status));
6080                 return false;
6081         }
6082
6083         status = cli_unlink(
6084                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6085         if (!NT_STATUS_IS_OK(status)) {
6086                 d_fprintf(stderr,
6087                           "unlink failed: %s\n",
6088                           nt_errstr(status));
6089                 return false;
6090         }
6091
6092         return true;
6093 }
6094
6095 /*
6096   Exercise delete on close semantics - use on the PRINT1 share in torture
6097   testing.
6098  */
6099 static bool run_delete_print_test(int dummy)
6100 {
6101         struct cli_state *cli1 = NULL;
6102         const char *fname = "print_delete.file";
6103         uint16_t fnum1 = (uint16_t)-1;
6104         bool correct = false;
6105         const char *buf = "print file data\n";
6106         NTSTATUS status;
6107
6108         printf("starting print delete test\n");
6109
6110         if (!torture_open_connection(&cli1, 0)) {
6111                 return false;
6112         }
6113
6114         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6115
6116         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6117                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6118                               0, 0, &fnum1, NULL);
6119         if (!NT_STATUS_IS_OK(status)) {
6120                 printf("open of %s failed (%s)\n",
6121                         fname,
6122                         nt_errstr(status));
6123                 goto fail;
6124         }
6125
6126         status = cli_writeall(cli1,
6127                         fnum1,
6128                         0,
6129                         (const uint8_t *)buf,
6130                         0, /* offset */
6131                         strlen(buf), /* size */
6132                         NULL);
6133         if (!NT_STATUS_IS_OK(status)) {
6134                 printf("writing print file data failed (%s)\n",
6135                         nt_errstr(status));
6136                 goto fail;
6137         }
6138
6139         status = cli_nt_delete_on_close(cli1, fnum1, true);
6140         if (!NT_STATUS_IS_OK(status)) {
6141                 printf("setting delete_on_close failed (%s)\n",
6142                         nt_errstr(status));
6143                 goto fail;
6144         }
6145
6146         status = cli_close(cli1, fnum1);
6147         if (!NT_STATUS_IS_OK(status)) {
6148                 printf("close failed (%s)\n", nt_errstr(status));
6149                 goto fail;
6150         }
6151
6152         printf("finished print delete test\n");
6153
6154         correct = true;
6155
6156   fail:
6157
6158         if (fnum1 != (uint16_t)-1) {
6159                 cli_close(cli1, fnum1);
6160         }
6161
6162         if (cli1 && !torture_close_connection(cli1)) {
6163                 correct = false;
6164         }
6165         return correct;
6166 }
6167
6168 static bool run_deletetest_ln(int dummy)
6169 {
6170         struct cli_state *cli;
6171         const char *fname = "\\delete1";
6172         const char *fname_ln = "\\delete1_ln";
6173         uint16_t fnum;
6174         uint16_t fnum1;
6175         NTSTATUS status;
6176         bool correct = true;
6177         time_t t;
6178
6179         printf("starting deletetest-ln\n");
6180
6181         if (!torture_open_connection(&cli, 0)) {
6182                 return false;
6183         }
6184
6185         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6186         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6187
6188         smbXcli_conn_set_sockopt(cli->conn, sockops);
6189
6190         /* Create the file. */
6191         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6192         if (!NT_STATUS_IS_OK(status)) {
6193                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6194                 return false;
6195         }
6196
6197         status = cli_close(cli, fnum);
6198         if (!NT_STATUS_IS_OK(status)) {
6199                 printf("close1 failed (%s)\n", nt_errstr(status));
6200                 return false;
6201         }
6202
6203         /* Now create a hardlink. */
6204         status = cli_hardlink(cli, fname, fname_ln);
6205         if (!NT_STATUS_IS_OK(status)) {
6206                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6207                 return false;
6208         }
6209
6210         /* Open the original file. */
6211         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6212                         FILE_ATTRIBUTE_NORMAL,
6213                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6214                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6215         if (!NT_STATUS_IS_OK(status)) {
6216                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6217                 return false;
6218         }
6219
6220         /* Unlink the hard link path. */
6221         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6222                         FILE_ATTRIBUTE_NORMAL,
6223                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6224                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6225         if (!NT_STATUS_IS_OK(status)) {
6226                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6227                 return false;
6228         }
6229         status = cli_nt_delete_on_close(cli, fnum1, true);
6230         if (!NT_STATUS_IS_OK(status)) {
6231                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6232                         __location__, fname_ln, nt_errstr(status));
6233                 return false;
6234         }
6235
6236         status = cli_close(cli, fnum1);
6237         if (!NT_STATUS_IS_OK(status)) {
6238                 printf("close %s failed (%s)\n",
6239                         fname_ln, nt_errstr(status));
6240                 return false;
6241         }
6242
6243         status = cli_close(cli, fnum);
6244         if (!NT_STATUS_IS_OK(status)) {
6245                 printf("close %s failed (%s)\n",
6246                         fname, nt_errstr(status));
6247                 return false;
6248         }
6249
6250         /* Ensure the original file is still there. */
6251         status = cli_getatr(cli, fname, NULL, NULL, &t);
6252         if (!NT_STATUS_IS_OK(status)) {
6253                 printf("%s getatr on file %s failed (%s)\n",
6254                         __location__,
6255                         fname,
6256                         nt_errstr(status));
6257                 correct = False;
6258         }
6259
6260         /* Ensure the link path is gone. */
6261         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6262         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6263                 printf("%s, getatr for file %s returned wrong error code %s "
6264                         "- should have been deleted\n",
6265                         __location__,
6266                         fname_ln, nt_errstr(status));
6267                 correct = False;
6268         }
6269
6270         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6271         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6272
6273         if (!torture_close_connection(cli)) {
6274                 correct = false;
6275         }
6276
6277         printf("finished deletetest-ln\n");
6278
6279         return correct;
6280 }
6281
6282 /*
6283   print out server properties
6284  */
6285 static bool run_properties(int dummy)
6286 {
6287         struct cli_state *cli;
6288         bool correct = True;
6289
6290         printf("starting properties test\n");
6291
6292         ZERO_STRUCT(cli);
6293
6294         if (!torture_open_connection(&cli, 0)) {
6295                 return False;
6296         }
6297
6298         smbXcli_conn_set_sockopt(cli->conn, sockops);
6299
6300         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6301
6302         if (!torture_close_connection(cli)) {
6303                 correct = False;
6304         }
6305
6306         return correct;
6307 }
6308
6309
6310
6311 /* FIRST_DESIRED_ACCESS   0xf019f */
6312 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6313                                FILE_READ_EA|                           /* 0xf */ \
6314                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6315                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6316                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6317                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6318 /* SECOND_DESIRED_ACCESS  0xe0080 */
6319 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6320                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6321                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6322
6323 #if 0
6324 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6325                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6326                                FILE_READ_DATA|\
6327                                WRITE_OWNER_ACCESS                      /* */
6328 #endif
6329
6330 /*
6331   Test ntcreate calls made by xcopy
6332  */
6333 static bool run_xcopy(int dummy)
6334 {
6335         static struct cli_state *cli1;
6336         const char *fname = "\\test.txt";
6337         bool correct = True;
6338         uint16_t fnum1, fnum2;
6339         NTSTATUS status;
6340
6341         printf("starting xcopy test\n");
6342
6343         if (!torture_open_connection(&cli1, 0)) {
6344                 return False;
6345         }
6346
6347         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6348                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6349                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6350         if (!NT_STATUS_IS_OK(status)) {
6351                 printf("First open failed - %s\n", nt_errstr(status));
6352                 return False;
6353         }
6354
6355         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6356                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6357                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6358         if (!NT_STATUS_IS_OK(status)) {
6359                 printf("second open failed - %s\n", nt_errstr(status));
6360                 return False;
6361         }
6362
6363         if (!torture_close_connection(cli1)) {
6364                 correct = False;
6365         }
6366
6367         return correct;
6368 }
6369
6370 /*
6371   Test rename on files open with share delete and no share delete.
6372  */
6373 static bool run_rename(int dummy)
6374 {
6375         static struct cli_state *cli1;
6376         const char *fname = "\\test.txt";
6377         const char *fname1 = "\\test1.txt";
6378         bool correct = True;
6379         uint16_t fnum1;
6380         uint32_t attr;
6381         NTSTATUS status;
6382
6383         printf("starting rename test\n");
6384
6385         if (!torture_open_connection(&cli1, 0)) {
6386                 return False;
6387         }
6388
6389         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6390         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6391
6392         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6393                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6394                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6395         if (!NT_STATUS_IS_OK(status)) {
6396                 printf("First open failed - %s\n", nt_errstr(status));
6397                 return False;
6398         }
6399
6400         status = cli_rename(cli1, fname, fname1, false);
6401         if (!NT_STATUS_IS_OK(status)) {
6402                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6403         } else {
6404                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6405                 correct = False;
6406         }
6407
6408         status = cli_close(cli1, fnum1);
6409         if (!NT_STATUS_IS_OK(status)) {
6410                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6411                 return False;
6412         }
6413
6414         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6415         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6416         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6417 #if 0
6418                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6419 #else
6420                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6421 #endif
6422                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6423         if (!NT_STATUS_IS_OK(status)) {
6424                 printf("Second open failed - %s\n", nt_errstr(status));
6425                 return False;
6426         }
6427
6428         status = cli_rename(cli1, fname, fname1, false);
6429         if (!NT_STATUS_IS_OK(status)) {
6430                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6431                 correct = False;
6432         } else {
6433                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6434         }
6435
6436         status = cli_close(cli1, fnum1);
6437         if (!NT_STATUS_IS_OK(status)) {
6438                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6439                 return False;
6440         }
6441
6442         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6443         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6444
6445         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6446                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6447                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6448         if (!NT_STATUS_IS_OK(status)) {
6449                 printf("Third open failed - %s\n", nt_errstr(status));
6450                 return False;
6451         }
6452
6453
6454         status = cli_rename(cli1, fname, fname1, false);
6455         if (!NT_STATUS_IS_OK(status)) {
6456                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6457                 correct = False;
6458         } else {
6459                 printf("Third rename succeeded (SHARE_NONE)\n");
6460         }
6461
6462         status = cli_close(cli1, fnum1);
6463         if (!NT_STATUS_IS_OK(status)) {
6464                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6465                 return False;
6466         }
6467
6468         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6469         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6470
6471         /*----*/
6472
6473         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6474                               FILE_ATTRIBUTE_NORMAL,
6475                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6476                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6477         if (!NT_STATUS_IS_OK(status)) {
6478                 printf("Fourth open failed - %s\n", nt_errstr(status));
6479                 return False;
6480         }
6481
6482         status = cli_rename(cli1, fname, fname1, false);
6483         if (!NT_STATUS_IS_OK(status)) {
6484                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6485         } else {
6486                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6487                 correct = False;
6488         }
6489
6490         status = cli_close(cli1, fnum1);
6491         if (!NT_STATUS_IS_OK(status)) {
6492                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6493                 return False;
6494         }
6495
6496         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6497         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6498
6499         /*--*/
6500
6501         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6502                          FILE_ATTRIBUTE_NORMAL,
6503                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6504                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6505         if (!NT_STATUS_IS_OK(status)) {
6506                 printf("Fifth open failed - %s\n", nt_errstr(status));
6507                 return False;
6508         }
6509
6510         status = cli_rename(cli1, fname, fname1, false);
6511         if (!NT_STATUS_IS_OK(status)) {
6512                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6513                 correct = False;
6514         } else {
6515                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6516         }
6517
6518         /*--*/
6519         status = cli_close(cli1, fnum1);
6520         if (!NT_STATUS_IS_OK(status)) {
6521                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6522                 return False;
6523         }
6524
6525         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6526         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6527         if (!NT_STATUS_IS_OK(status)) {
6528                 printf("getatr on file %s failed - %s ! \n",
6529                         fname1, nt_errstr(status));
6530                 correct = False;
6531         } else {
6532                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6533                         printf("Renamed file %s has wrong attr 0x%x "
6534                                 "(should be 0x%x)\n",
6535                                 fname1,
6536                                 attr,
6537                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6538                         correct = False;
6539                 } else {
6540                         printf("Renamed file %s has archive bit set\n", fname1);
6541                 }
6542         }
6543
6544         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6545         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6546
6547         if (!torture_close_connection(cli1)) {
6548                 correct = False;
6549         }
6550
6551         return correct;
6552 }
6553
6554 /*
6555   Test rename into a directory with an ACL denying it.
6556  */
6557 static bool run_rename_access(int dummy)
6558 {
6559         static struct cli_state *cli = NULL;
6560         static struct cli_state *posix_cli = NULL;
6561         const char *src = "test.txt";
6562         const char *dname = "dir";
6563         const char *dst = "dir\\test.txt";
6564         const char *dsrc = "test.dir";
6565         const char *ddst = "dir\\test.dir";
6566         uint16_t fnum = (uint16_t)-1;
6567         struct security_descriptor *sd = NULL;
6568         struct security_descriptor *newsd = NULL;
6569         NTSTATUS status;
6570         TALLOC_CTX *frame = NULL;
6571
6572         frame = talloc_stackframe();
6573         printf("starting rename access test\n");
6574
6575         /* Windows connection. */
6576         if (!torture_open_connection(&cli, 0)) {
6577                 goto fail;
6578         }
6579
6580         smbXcli_conn_set_sockopt(cli->conn, sockops);
6581
6582         /* Posix connection. */
6583         if (!torture_open_connection(&posix_cli, 0)) {
6584                 goto fail;
6585         }
6586
6587         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6588
6589         status = torture_setup_unix_extensions(posix_cli);
6590         if (!NT_STATUS_IS_OK(status)) {
6591                 goto fail;
6592         }
6593
6594         /* Start with a clean slate. */
6595         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6596         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6597         cli_rmdir(cli, dsrc);
6598         cli_rmdir(cli, ddst);
6599         cli_rmdir(cli, dname);
6600
6601         /*
6602          * Setup the destination directory with a DENY ACE to
6603          * prevent new files within it.
6604          */
6605         status = cli_ntcreate(cli,
6606                                 dname,
6607                                 0,
6608                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6609                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6610                                         WRITE_OWNER_ACCESS,
6611                                 FILE_ATTRIBUTE_DIRECTORY,
6612                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6613                                 FILE_CREATE,
6614                                 FILE_DIRECTORY_FILE,
6615                                 0,
6616                                 &fnum,
6617                                 NULL);
6618         if (!NT_STATUS_IS_OK(status)) {
6619                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6620                 goto fail;
6621         }
6622
6623         status = cli_query_secdesc(cli,
6624                                 fnum,
6625                                 frame,
6626                                 &sd);
6627         if (!NT_STATUS_IS_OK(status)) {
6628                 printf("cli_query_secdesc failed for %s (%s)\n",
6629                         dname, nt_errstr(status));
6630                 goto fail;
6631         }
6632
6633         newsd = security_descriptor_dacl_create(frame,
6634                                         0,
6635                                         NULL,
6636                                         NULL,
6637                                         SID_WORLD,
6638                                         SEC_ACE_TYPE_ACCESS_DENIED,
6639                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6640                                         0,
6641                                         NULL);
6642         if (newsd == NULL) {
6643                 goto fail;
6644         }
6645         sd->dacl = security_acl_concatenate(frame,
6646                                         newsd->dacl,
6647                                         sd->dacl);
6648         if (sd->dacl == NULL) {
6649                 goto fail;
6650         }
6651         status = cli_set_secdesc(cli, fnum, sd);
6652         if (!NT_STATUS_IS_OK(status)) {
6653                 printf("cli_set_secdesc failed for %s (%s)\n",
6654                         dname, nt_errstr(status));
6655                 goto fail;
6656         }
6657         status = cli_close(cli, fnum);
6658         if (!NT_STATUS_IS_OK(status)) {
6659                 printf("close failed for %s (%s)\n",
6660                         dname, nt_errstr(status));
6661                 goto fail;
6662         }
6663         /* Now go around the back and chmod to 777 via POSIX. */
6664         status = cli_posix_chmod(posix_cli, dname, 0777);
6665         if (!NT_STATUS_IS_OK(status)) {
6666                 printf("cli_posix_chmod failed for %s (%s)\n",
6667                         dname, nt_errstr(status));
6668                 goto fail;
6669         }
6670
6671         /* Check we can't create a file within dname via Windows. */
6672         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6673         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6674                 cli_close(posix_cli, fnum);
6675                 printf("Create of %s should be ACCESS denied, was %s\n",
6676                         dst, nt_errstr(status));
6677                 goto fail;
6678         }
6679
6680         /* Make the sample file/directory. */
6681         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6682         if (!NT_STATUS_IS_OK(status)) {
6683                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6684                 goto fail;
6685         }
6686         status = cli_close(cli, fnum);
6687         if (!NT_STATUS_IS_OK(status)) {
6688                 printf("cli_close failed (%s)\n", nt_errstr(status));
6689                 goto fail;
6690         }
6691
6692         status = cli_mkdir(cli, dsrc);
6693         if (!NT_STATUS_IS_OK(status)) {
6694                 printf("cli_mkdir of %s failed (%s)\n",
6695                         dsrc, nt_errstr(status));
6696                 goto fail;
6697         }
6698
6699         /*
6700          * OK - renames of the new file and directory into the
6701          * dst directory should fail.
6702          */
6703
6704         status = cli_rename(cli, src, dst, false);
6705         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6706                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6707                         src, dst, nt_errstr(status));
6708                 goto fail;
6709         }
6710         status = cli_rename(cli, dsrc, ddst, false);
6711         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6712                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6713                         src, dst, nt_errstr(status));
6714                 goto fail;
6715         }
6716
6717         TALLOC_FREE(frame);
6718         return true;
6719
6720   fail:
6721
6722         if (posix_cli) {
6723                 torture_close_connection(posix_cli);
6724         }
6725
6726         if (cli) {
6727                 if (fnum != (uint16_t)-1) {
6728                         cli_close(cli, fnum);
6729                 }
6730                 cli_unlink(cli, src,
6731                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6732                 cli_unlink(cli, dst,
6733                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6734                 cli_rmdir(cli, dsrc);
6735                 cli_rmdir(cli, ddst);
6736                 cli_rmdir(cli, dname);
6737
6738                 torture_close_connection(cli);
6739         }
6740
6741         TALLOC_FREE(frame);
6742         return false;
6743 }
6744
6745 /*
6746   Test owner rights ACE.
6747  */
6748 static bool run_owner_rights(int dummy)
6749 {
6750         static struct cli_state *cli = NULL;
6751         const char *fname = "owner_rights.txt";
6752         uint16_t fnum = (uint16_t)-1;
6753         struct security_descriptor *sd = NULL;
6754         struct security_descriptor *newsd = NULL;
6755         NTSTATUS status;
6756         TALLOC_CTX *frame = NULL;
6757
6758         frame = talloc_stackframe();
6759         printf("starting owner rights test\n");
6760
6761         /* Windows connection. */
6762         if (!torture_open_connection(&cli, 0)) {
6763                 goto fail;
6764         }
6765
6766         smbXcli_conn_set_sockopt(cli->conn, sockops);
6767
6768         /* Start with a clean slate. */
6769         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6770
6771         /* Create the test file. */
6772         /* Now try and open for read and write-dac. */
6773         status = cli_ntcreate(cli,
6774                                 fname,
6775                                 0,
6776                                 GENERIC_ALL_ACCESS,
6777                                 FILE_ATTRIBUTE_NORMAL,
6778                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6779                                         FILE_SHARE_DELETE,
6780                                 FILE_CREATE,
6781                                 0,
6782                                 0,
6783                                 &fnum,
6784                                 NULL);
6785         if (!NT_STATUS_IS_OK(status)) {
6786                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6787                 goto fail;
6788         }
6789
6790         /* Get the original SD. */
6791         status = cli_query_secdesc(cli,
6792                                 fnum,
6793                                 frame,
6794                                 &sd);
6795         if (!NT_STATUS_IS_OK(status)) {
6796                 printf("cli_query_secdesc failed for %s (%s)\n",
6797                         fname, nt_errstr(status));
6798                 goto fail;
6799         }
6800
6801         /*
6802          * Add an "owner-rights" ACE denying WRITE_DATA,
6803          * and an "owner-rights" ACE allowing READ_DATA.
6804          */
6805
6806         newsd = security_descriptor_dacl_create(frame,
6807                                         0,
6808                                         NULL,
6809                                         NULL,
6810                                         SID_OWNER_RIGHTS,
6811                                         SEC_ACE_TYPE_ACCESS_DENIED,
6812                                         FILE_WRITE_DATA,
6813                                         0,
6814                                         SID_OWNER_RIGHTS,
6815                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6816                                         FILE_READ_DATA,
6817                                         0,
6818                                         NULL);
6819         if (newsd == NULL) {
6820                 goto fail;
6821         }
6822         sd->dacl = security_acl_concatenate(frame,
6823                                         newsd->dacl,
6824                                         sd->dacl);
6825         if (sd->dacl == NULL) {
6826                 goto fail;
6827         }
6828         status = cli_set_secdesc(cli, fnum, sd);
6829         if (!NT_STATUS_IS_OK(status)) {
6830                 printf("cli_set_secdesc failed for %s (%s)\n",
6831                         fname, nt_errstr(status));
6832                 goto fail;
6833         }
6834         status = cli_close(cli, fnum);
6835         if (!NT_STATUS_IS_OK(status)) {
6836                 printf("close failed for %s (%s)\n",
6837                         fname, nt_errstr(status));
6838                 goto fail;
6839         }
6840         fnum = (uint16_t)-1;
6841
6842         /* Try and open for FILE_WRITE_DATA */
6843         status = cli_ntcreate(cli,
6844                                 fname,
6845                                 0,
6846                                 FILE_WRITE_DATA,
6847                                 FILE_ATTRIBUTE_NORMAL,
6848                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6849                                         FILE_SHARE_DELETE,
6850                                 FILE_OPEN,
6851                                 0,
6852                                 0,
6853                                 &fnum,
6854                                 NULL);
6855         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6856                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6857                 goto fail;
6858         }
6859
6860         /* Now try and open for FILE_READ_DATA */
6861         status = cli_ntcreate(cli,
6862                                 fname,
6863                                 0,
6864                                 FILE_READ_DATA,
6865                                 FILE_ATTRIBUTE_NORMAL,
6866                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6867                                         FILE_SHARE_DELETE,
6868                                 FILE_OPEN,
6869                                 0,
6870                                 0,
6871                                 &fnum,
6872                                 NULL);
6873         if (!NT_STATUS_IS_OK(status)) {
6874                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6875                 goto fail;
6876         }
6877
6878         status = cli_close(cli, fnum);
6879         if (!NT_STATUS_IS_OK(status)) {
6880                 printf("close failed for %s (%s)\n",
6881                         fname, nt_errstr(status));
6882                 goto fail;
6883         }
6884
6885         /* Restore clean slate. */
6886         TALLOC_FREE(sd);
6887         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6888
6889         /* Create the test file. */
6890         status = cli_ntcreate(cli,
6891                                 fname,
6892                                 0,
6893                                 GENERIC_ALL_ACCESS,
6894                                 FILE_ATTRIBUTE_NORMAL,
6895                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6896                                         FILE_SHARE_DELETE,
6897                                 FILE_CREATE,
6898                                 0,
6899                                 0,
6900                                 &fnum,
6901                                 NULL);
6902         if (!NT_STATUS_IS_OK(status)) {
6903                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6904                 goto fail;
6905         }
6906
6907         /* Get the original SD. */
6908         status = cli_query_secdesc(cli,
6909                                 fnum,
6910                                 frame,
6911                                 &sd);
6912         if (!NT_STATUS_IS_OK(status)) {
6913                 printf("cli_query_secdesc failed for %s (%s)\n",
6914                         fname, nt_errstr(status));
6915                 goto fail;
6916         }
6917
6918         /*
6919          * Add an "owner-rights ACE denying WRITE_DATA,
6920          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6921          */
6922
6923         newsd = security_descriptor_dacl_create(frame,
6924                                         0,
6925                                         NULL,
6926                                         NULL,
6927                                         SID_OWNER_RIGHTS,
6928                                         SEC_ACE_TYPE_ACCESS_DENIED,
6929                                         FILE_WRITE_DATA,
6930                                         0,
6931                                         SID_OWNER_RIGHTS,
6932                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6933                                         FILE_READ_DATA|FILE_WRITE_DATA,
6934                                         0,
6935                                         NULL);
6936         if (newsd == NULL) {
6937                 goto fail;
6938         }
6939         sd->dacl = security_acl_concatenate(frame,
6940                                         newsd->dacl,
6941                                         sd->dacl);
6942         if (sd->dacl == NULL) {
6943                 goto fail;
6944         }
6945         status = cli_set_secdesc(cli, fnum, sd);
6946         if (!NT_STATUS_IS_OK(status)) {
6947                 printf("cli_set_secdesc failed for %s (%s)\n",
6948                         fname, nt_errstr(status));
6949                 goto fail;
6950         }
6951         status = cli_close(cli, fnum);
6952         if (!NT_STATUS_IS_OK(status)) {
6953                 printf("close failed for %s (%s)\n",
6954                         fname, nt_errstr(status));
6955                 goto fail;
6956         }
6957         fnum = (uint16_t)-1;
6958
6959         /* Try and open for FILE_WRITE_DATA */
6960         status = cli_ntcreate(cli,
6961                                 fname,
6962                                 0,
6963                                 FILE_WRITE_DATA,
6964                                 FILE_ATTRIBUTE_NORMAL,
6965                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6966                                         FILE_SHARE_DELETE,
6967                                 FILE_OPEN,
6968                                 0,
6969                                 0,
6970                                 &fnum,
6971                                 NULL);
6972         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6973                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6974                 goto fail;
6975         }
6976
6977         /* Now try and open for FILE_READ_DATA */
6978         status = cli_ntcreate(cli,
6979                                 fname,
6980                                 0,
6981                                 FILE_READ_DATA,
6982                                 FILE_ATTRIBUTE_NORMAL,
6983                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6984                                         FILE_SHARE_DELETE,
6985                                 FILE_OPEN,
6986                                 0,
6987                                 0,
6988                                 &fnum,
6989                                 NULL);
6990         if (!NT_STATUS_IS_OK(status)) {
6991                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6992                 goto fail;
6993         }
6994
6995         status = cli_close(cli, fnum);
6996         if (!NT_STATUS_IS_OK(status)) {
6997                 printf("close failed for %s (%s)\n",
6998                         fname, nt_errstr(status));
6999                 goto fail;
7000         }
7001
7002         /* Restore clean slate. */
7003         TALLOC_FREE(sd);
7004         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7005
7006
7007         /* Create the test file. */
7008         status = cli_ntcreate(cli,
7009                                 fname,
7010                                 0,
7011                                 GENERIC_ALL_ACCESS,
7012                                 FILE_ATTRIBUTE_NORMAL,
7013                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7014                                         FILE_SHARE_DELETE,
7015                                 FILE_CREATE,
7016                                 0,
7017                                 0,
7018                                 &fnum,
7019                                 NULL);
7020         if (!NT_STATUS_IS_OK(status)) {
7021                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7022                 goto fail;
7023         }
7024
7025         /* Get the original SD. */
7026         status = cli_query_secdesc(cli,
7027                                 fnum,
7028                                 frame,
7029                                 &sd);
7030         if (!NT_STATUS_IS_OK(status)) {
7031                 printf("cli_query_secdesc failed for %s (%s)\n",
7032                         fname, nt_errstr(status));
7033                 goto fail;
7034         }
7035
7036         /*
7037          * Add an "authenticated users" ACE allowing READ_DATA,
7038          * add an "owner-rights" denying READ_DATA,
7039          * and an "authenticated users" ACE allowing WRITE_DATA.
7040          */
7041
7042         newsd = security_descriptor_dacl_create(frame,
7043                                         0,
7044                                         NULL,
7045                                         NULL,
7046                                         SID_NT_AUTHENTICATED_USERS,
7047                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7048                                         FILE_READ_DATA,
7049                                         0,
7050                                         SID_OWNER_RIGHTS,
7051                                         SEC_ACE_TYPE_ACCESS_DENIED,
7052                                         FILE_READ_DATA,
7053                                         0,
7054                                         SID_NT_AUTHENTICATED_USERS,
7055                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7056                                         FILE_WRITE_DATA,
7057                                         0,
7058                                         NULL);
7059         if (newsd == NULL) {
7060                 printf("newsd == NULL\n");
7061                 goto fail;
7062         }
7063         sd->dacl = security_acl_concatenate(frame,
7064                                         newsd->dacl,
7065                                         sd->dacl);
7066         if (sd->dacl == NULL) {
7067                 printf("sd->dacl == NULL\n");
7068                 goto fail;
7069         }
7070         status = cli_set_secdesc(cli, fnum, sd);
7071         if (!NT_STATUS_IS_OK(status)) {
7072                 printf("cli_set_secdesc failed for %s (%s)\n",
7073                         fname, nt_errstr(status));
7074                 goto fail;
7075         }
7076         status = cli_close(cli, fnum);
7077         if (!NT_STATUS_IS_OK(status)) {
7078                 printf("close failed for %s (%s)\n",
7079                         fname, nt_errstr(status));
7080                 goto fail;
7081         }
7082         fnum = (uint16_t)-1;
7083
7084         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7085         status = cli_ntcreate(cli,
7086                                 fname,
7087                                 0,
7088                                 FILE_READ_DATA|FILE_WRITE_DATA,
7089                                 FILE_ATTRIBUTE_NORMAL,
7090                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7091                                         FILE_SHARE_DELETE,
7092                                 FILE_OPEN,
7093                                 0,
7094                                 0,
7095                                 &fnum,
7096                                 NULL);
7097         if (!NT_STATUS_IS_OK(status)) {
7098                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7099                 goto fail;
7100         }
7101
7102         status = cli_close(cli, fnum);
7103         if (!NT_STATUS_IS_OK(status)) {
7104                 printf("close failed for %s (%s)\n",
7105                         fname, nt_errstr(status));
7106                 goto fail;
7107         }
7108
7109         cli_unlink(cli, fname,
7110                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7111
7112         TALLOC_FREE(frame);
7113         return true;
7114
7115   fail:
7116
7117         if (cli) {
7118                 if (fnum != (uint16_t)-1) {
7119                         cli_close(cli, fnum);
7120                 }
7121                 cli_unlink(cli, fname,
7122                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7123                 torture_close_connection(cli);
7124         }
7125
7126         TALLOC_FREE(frame);
7127         return false;
7128 }
7129
7130 /*
7131  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7132  * Note this test only works with a user with SeSecurityPrivilege set.
7133  *
7134  * NB. This is also tested in samba3.base.createx_access
7135  * but this makes it very explicit what we're looking for.
7136  */
7137 static bool run_smb1_system_security(int dummy)
7138 {
7139         static struct cli_state *cli = NULL;
7140         const char *fname = "system_security.txt";
7141         uint16_t fnum = (uint16_t)-1;
7142         NTSTATUS status;
7143         TALLOC_CTX *frame = NULL;
7144
7145         frame = talloc_stackframe();
7146         printf("starting smb1 system security test\n");
7147
7148         /* SMB1 connection - torture_open_connection() forces this. */
7149         if (!torture_open_connection(&cli, 0)) {
7150                 goto fail;
7151         }
7152
7153         smbXcli_conn_set_sockopt(cli->conn, sockops);
7154
7155         /* Start with a clean slate. */
7156         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7157
7158         /* Create the test file. */
7159         status = cli_ntcreate(cli,
7160                                 fname,
7161                                 0,
7162                                 GENERIC_ALL_ACCESS,
7163                                 FILE_ATTRIBUTE_NORMAL,
7164                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7165                                         FILE_SHARE_DELETE,
7166                                 FILE_CREATE,
7167                                 0,
7168                                 0,
7169                                 &fnum,
7170                                 NULL);
7171         if (!NT_STATUS_IS_OK(status)) {
7172                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7173                 goto fail;
7174         }
7175
7176         status = cli_close(cli, fnum);
7177
7178         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7179         /*
7180          * On SMB1 this succeeds - SMB2 it fails,
7181          * see the SMB2-SACL test.
7182          */
7183         status = cli_ntcreate(cli,
7184                                 fname,
7185                                 0,
7186                                 SEC_FLAG_SYSTEM_SECURITY,
7187                                 FILE_ATTRIBUTE_NORMAL,
7188                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7189                                         FILE_SHARE_DELETE,
7190                                 FILE_OPEN,
7191                                 0,
7192                                 0,
7193                                 &fnum,
7194                                 NULL);
7195         if (!NT_STATUS_IS_OK(status)) {
7196                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7197                 goto fail;
7198         }
7199
7200         status = cli_close(cli, fnum);
7201
7202         cli_unlink(cli, fname,
7203                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7204
7205         torture_close_connection(cli);
7206         TALLOC_FREE(frame);
7207         return true;
7208
7209   fail:
7210
7211         if (cli) {
7212                 if (fnum != (uint16_t)-1) {
7213                         cli_close(cli, fnum);
7214                 }
7215                 cli_unlink(cli, fname,
7216                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7217                 torture_close_connection(cli);
7218         }
7219
7220         TALLOC_FREE(frame);
7221         return false;
7222 }
7223
7224 static bool run_pipe_number(int dummy)
7225 {
7226         struct cli_state *cli1;
7227         const char *pipe_name = "\\SPOOLSS";
7228         uint16_t fnum;
7229         int num_pipes = 0;
7230         NTSTATUS status;
7231
7232         printf("starting pipenumber test\n");
7233         if (!torture_open_connection(&cli1, 0)) {
7234                 return False;
7235         }
7236
7237         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7238         while(1) {
7239                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7240                                       FILE_ATTRIBUTE_NORMAL,
7241                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7242                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7243                 if (!NT_STATUS_IS_OK(status)) {
7244                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7245                         break;
7246                 }
7247                 num_pipes++;
7248                 printf("\r%6d", num_pipes);
7249         }
7250
7251         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7252         torture_close_connection(cli1);
7253         return True;
7254 }
7255
7256 /*
7257   Test open mode returns on read-only files.
7258  */
7259 static bool run_opentest(int dummy)
7260 {
7261         static struct cli_state *cli1;
7262         static struct cli_state *cli2;
7263         const char *fname = "\\readonly.file";
7264         uint16_t fnum1, fnum2;
7265         char buf[20];
7266         off_t fsize;
7267         bool correct = True;
7268         char *tmp_path;
7269         NTSTATUS status;
7270
7271         printf("starting open test\n");
7272
7273         if (!torture_open_connection(&cli1, 0)) {
7274                 return False;
7275         }
7276
7277         cli_setatr(cli1, fname, 0, 0);
7278         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7279
7280         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7281
7282         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7283         if (!NT_STATUS_IS_OK(status)) {
7284                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7285                 return False;
7286         }
7287
7288         status = cli_close(cli1, fnum1);
7289         if (!NT_STATUS_IS_OK(status)) {
7290                 printf("close2 failed (%s)\n", nt_errstr(status));
7291                 return False;
7292         }
7293
7294         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7295         if (!NT_STATUS_IS_OK(status)) {
7296                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7297                 return False;
7298         }
7299
7300         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7301         if (!NT_STATUS_IS_OK(status)) {
7302                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7303                 return False;
7304         }
7305
7306         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7307         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7308
7309         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7310                         NT_STATUS_ACCESS_DENIED)) {
7311                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7312         }
7313
7314         printf("finished open test 1\n");
7315
7316         cli_close(cli1, fnum1);
7317
7318         /* Now try not readonly and ensure ERRbadshare is returned. */
7319
7320         cli_setatr(cli1, fname, 0, 0);
7321
7322         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7323         if (!NT_STATUS_IS_OK(status)) {
7324                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7325                 return False;
7326         }
7327
7328         /* This will fail - but the error should be ERRshare. */
7329         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7330
7331         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7332                         NT_STATUS_SHARING_VIOLATION)) {
7333                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7334         }
7335
7336         status = cli_close(cli1, fnum1);
7337         if (!NT_STATUS_IS_OK(status)) {
7338                 printf("close2 failed (%s)\n", nt_errstr(status));
7339                 return False;
7340         }
7341
7342         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7343
7344         printf("finished open test 2\n");
7345
7346         /* Test truncate open disposition on file opened for read. */
7347         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7348         if (!NT_STATUS_IS_OK(status)) {
7349                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7350                 return False;
7351         }
7352
7353         /* write 20 bytes. */
7354
7355         memset(buf, '\0', 20);
7356
7357         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7358         if (!NT_STATUS_IS_OK(status)) {
7359                 printf("write failed (%s)\n", nt_errstr(status));
7360                 correct = False;
7361         }
7362
7363         status = cli_close(cli1, fnum1);
7364         if (!NT_STATUS_IS_OK(status)) {
7365                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7366                 return False;
7367         }
7368
7369         /* Ensure size == 20. */
7370         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7371         if (!NT_STATUS_IS_OK(status)) {
7372                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7373                 return False;
7374         }
7375
7376         if (fsize != 20) {
7377                 printf("(3) file size != 20\n");
7378                 return False;
7379         }
7380
7381         /* Now test if we can truncate a file opened for readonly. */
7382         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7383         if (!NT_STATUS_IS_OK(status)) {
7384                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7385                 return False;
7386         }
7387
7388         status = cli_close(cli1, fnum1);
7389         if (!NT_STATUS_IS_OK(status)) {
7390                 printf("close2 failed (%s)\n", nt_errstr(status));
7391                 return False;
7392         }
7393
7394         /* Ensure size == 0. */
7395         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7396         if (!NT_STATUS_IS_OK(status)) {
7397                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7398                 return False;
7399         }
7400
7401         if (fsize != 0) {
7402                 printf("(3) file size != 0\n");
7403                 return False;
7404         }
7405         printf("finished open test 3\n");
7406
7407         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7408
7409         printf("Do ctemp tests\n");
7410         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7411         if (!NT_STATUS_IS_OK(status)) {
7412                 printf("ctemp failed (%s)\n", nt_errstr(status));
7413                 return False;
7414         }
7415
7416         printf("ctemp gave path %s\n", tmp_path);
7417         status = cli_close(cli1, fnum1);
7418         if (!NT_STATUS_IS_OK(status)) {
7419                 printf("close of temp failed (%s)\n", nt_errstr(status));
7420         }
7421
7422         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7423         if (!NT_STATUS_IS_OK(status)) {
7424                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7425         }
7426
7427         /* Test the non-io opens... */
7428
7429         if (!torture_open_connection(&cli2, 1)) {
7430                 return False;
7431         }
7432
7433         cli_setatr(cli2, fname, 0, 0);
7434         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7435
7436         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7437
7438         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7439         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7440                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7441                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7442         if (!NT_STATUS_IS_OK(status)) {
7443                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7444                 return False;
7445         }
7446
7447         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7448                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7449                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7450         if (!NT_STATUS_IS_OK(status)) {
7451                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7452                 return False;
7453         }
7454
7455         status = cli_close(cli1, fnum1);
7456         if (!NT_STATUS_IS_OK(status)) {
7457                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7458                 return False;
7459         }
7460
7461         status = cli_close(cli2, fnum2);
7462         if (!NT_STATUS_IS_OK(status)) {
7463                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7464                 return False;
7465         }
7466
7467         printf("non-io open test #1 passed.\n");
7468
7469         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7470
7471         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7472
7473         status = cli_ntcreate(cli1, fname, 0,
7474                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7475                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7476                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7477         if (!NT_STATUS_IS_OK(status)) {
7478                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7479                 return False;
7480         }
7481
7482         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7483                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7484                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7485         if (!NT_STATUS_IS_OK(status)) {
7486                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7487                 return False;
7488         }
7489
7490         status = cli_close(cli1, fnum1);
7491         if (!NT_STATUS_IS_OK(status)) {
7492                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7493                 return False;
7494         }
7495
7496         status = cli_close(cli2, fnum2);
7497         if (!NT_STATUS_IS_OK(status)) {
7498                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7499                 return False;
7500         }
7501
7502         printf("non-io open test #2 passed.\n");
7503
7504         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7505
7506         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7507
7508         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7509                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7510                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7511         if (!NT_STATUS_IS_OK(status)) {
7512                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7513                 return False;
7514         }
7515
7516         status = cli_ntcreate(cli2, fname, 0,
7517                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7518                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7519                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7520         if (!NT_STATUS_IS_OK(status)) {
7521                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7522                 return False;
7523         }
7524
7525         status = cli_close(cli1, fnum1);
7526         if (!NT_STATUS_IS_OK(status)) {
7527                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7528                 return False;
7529         }
7530
7531         status = cli_close(cli2, fnum2);
7532         if (!NT_STATUS_IS_OK(status)) {
7533                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7534                 return False;
7535         }
7536
7537         printf("non-io open test #3 passed.\n");
7538
7539         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7540
7541         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7542
7543         status = cli_ntcreate(cli1, fname, 0,
7544                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7545                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7546                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7547         if (!NT_STATUS_IS_OK(status)) {
7548                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7549                 return False;
7550         }
7551
7552         status = cli_ntcreate(cli2, fname, 0,
7553                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7554                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7555                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7556         if (NT_STATUS_IS_OK(status)) {
7557                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7558                 return False;
7559         }
7560
7561         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7562
7563         status = cli_close(cli1, fnum1);
7564         if (!NT_STATUS_IS_OK(status)) {
7565                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7566                 return False;
7567         }
7568
7569         printf("non-io open test #4 passed.\n");
7570
7571         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7572
7573         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7574
7575         status = cli_ntcreate(cli1, fname, 0,
7576                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7577                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7578                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7579         if (!NT_STATUS_IS_OK(status)) {
7580                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7581                 return False;
7582         }
7583
7584         status = cli_ntcreate(cli2, fname, 0,
7585                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7586                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7587                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7588         if (!NT_STATUS_IS_OK(status)) {
7589                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7590                 return False;
7591         }
7592
7593         status = cli_close(cli1, fnum1);
7594         if (!NT_STATUS_IS_OK(status)) {
7595                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7596                 return False;
7597         }
7598
7599         status = cli_close(cli2, fnum2);
7600         if (!NT_STATUS_IS_OK(status)) {
7601                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7602                 return False;
7603         }
7604
7605         printf("non-io open test #5 passed.\n");
7606
7607         printf("TEST #6 testing 1 non-io open, one io open\n");
7608
7609         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7610
7611         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7612                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7613                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7614         if (!NT_STATUS_IS_OK(status)) {
7615                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7616                 return False;
7617         }
7618
7619         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7620                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7621                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7622         if (!NT_STATUS_IS_OK(status)) {
7623                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7624                 return False;
7625         }
7626
7627         status = cli_close(cli1, fnum1);
7628         if (!NT_STATUS_IS_OK(status)) {
7629                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7630                 return False;
7631         }
7632
7633         status = cli_close(cli2, fnum2);
7634         if (!NT_STATUS_IS_OK(status)) {
7635                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7636                 return False;
7637         }
7638
7639         printf("non-io open test #6 passed.\n");
7640
7641         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7642
7643         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7644
7645         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7646                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7647                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7648         if (!NT_STATUS_IS_OK(status)) {
7649                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7650                 return False;
7651         }
7652
7653         status = cli_ntcreate(cli2, fname, 0,
7654                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7655                               FILE_ATTRIBUTE_NORMAL,
7656                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7657                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7658         if (NT_STATUS_IS_OK(status)) {
7659                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7660                 return False;
7661         }
7662
7663         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7664
7665         status = cli_close(cli1, fnum1);
7666         if (!NT_STATUS_IS_OK(status)) {
7667                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7668                 return False;
7669         }
7670
7671         printf("non-io open test #7 passed.\n");
7672
7673         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7674
7675         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7676         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7677                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7678                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7679         if (!NT_STATUS_IS_OK(status)) {
7680                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7681                 correct = false;
7682                 goto out;
7683         }
7684
7685         /* Write to ensure we have to update the file time. */
7686         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7687                               NULL);
7688         if (!NT_STATUS_IS_OK(status)) {
7689                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7690                 correct = false;
7691                 goto out;
7692         }
7693
7694         status = cli_close(cli1, fnum1);
7695         if (!NT_STATUS_IS_OK(status)) {
7696                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7697                 correct = false;
7698         }
7699
7700   out:
7701
7702         if (!torture_close_connection(cli1)) {
7703                 correct = False;
7704         }
7705         if (!torture_close_connection(cli2)) {
7706                 correct = False;
7707         }
7708
7709         return correct;
7710 }
7711
7712 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7713 {
7714         uint16_t major, minor;
7715         uint32_t caplow, caphigh;
7716         NTSTATUS status;
7717
7718         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7719                 printf("Server doesn't support UNIX CIFS extensions.\n");
7720                 return NT_STATUS_NOT_SUPPORTED;
7721         }
7722
7723         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7724                                              &caphigh);
7725         if (!NT_STATUS_IS_OK(status)) {
7726                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7727                        nt_errstr(status));
7728                 return status;
7729         }
7730
7731         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7732                                                       caplow, caphigh);
7733         if (!NT_STATUS_IS_OK(status)) {
7734                 printf("Server doesn't support setting UNIX CIFS extensions: "
7735                        "%s.\n", nt_errstr(status));
7736                 return status;
7737         }
7738
7739         return NT_STATUS_OK;
7740 }
7741
7742 /*
7743   Test POSIX open /mkdir calls.
7744  */
7745 static bool run_simple_posix_open_test(int dummy)
7746 {
7747         static struct cli_state *cli1;
7748         const char *fname = "posix:file";
7749         const char *hname = "posix:hlink";
7750         const char *sname = "posix:symlink";
7751         const char *dname = "posix:dir";
7752         char buf[10];
7753         char *target = NULL;
7754         uint16_t fnum1 = (uint16_t)-1;
7755         SMB_STRUCT_STAT sbuf;
7756         bool correct = false;
7757         NTSTATUS status;
7758         size_t nread;
7759         const char *fname_windows = "windows_file";
7760         uint16_t fnum2 = (uint16_t)-1;
7761
7762         printf("Starting simple POSIX open test\n");
7763
7764         if (!torture_open_connection(&cli1, 0)) {
7765                 return false;
7766         }
7767
7768         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7769
7770         status = torture_setup_unix_extensions(cli1);
7771         if (!NT_STATUS_IS_OK(status)) {
7772                 return false;
7773         }
7774
7775         cli_setatr(cli1, fname, 0, 0);
7776         cli_posix_unlink(cli1, fname);
7777         cli_setatr(cli1, dname, 0, 0);
7778         cli_posix_rmdir(cli1, dname);
7779         cli_setatr(cli1, hname, 0, 0);
7780         cli_posix_unlink(cli1, hname);
7781         cli_setatr(cli1, sname, 0, 0);
7782         cli_posix_unlink(cli1, sname);
7783         cli_setatr(cli1, fname_windows, 0, 0);
7784         cli_posix_unlink(cli1, fname_windows);
7785
7786         /* Create a directory. */
7787         status = cli_posix_mkdir(cli1, dname, 0777);
7788         if (!NT_STATUS_IS_OK(status)) {
7789                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7790                 goto out;
7791         }
7792
7793         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7794                                 0600, &fnum1);
7795         if (!NT_STATUS_IS_OK(status)) {
7796                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7797                 goto out;
7798         }
7799
7800         /* Test ftruncate - set file size. */
7801         status = cli_ftruncate(cli1, fnum1, 1000);
7802         if (!NT_STATUS_IS_OK(status)) {
7803                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7804                 goto out;
7805         }
7806
7807         /* Ensure st_size == 1000 */
7808         status = cli_posix_stat(cli1, fname, &sbuf);
7809         if (!NT_STATUS_IS_OK(status)) {
7810                 printf("stat failed (%s)\n", nt_errstr(status));
7811                 goto out;
7812         }
7813
7814         if (sbuf.st_ex_size != 1000) {
7815                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7816                 goto out;
7817         }
7818
7819         /* Ensure st_mode == 0600 */
7820         if ((sbuf.st_ex_mode & 07777) != 0600) {
7821                 printf("posix_open - bad permissions 0%o != 0600\n",
7822                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7823                 goto out;
7824         }
7825
7826         /* Test ftruncate - set file size back to zero. */
7827         status = cli_ftruncate(cli1, fnum1, 0);
7828         if (!NT_STATUS_IS_OK(status)) {
7829                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7830                 goto out;
7831         }
7832
7833         status = cli_close(cli1, fnum1);
7834         if (!NT_STATUS_IS_OK(status)) {
7835                 printf("close failed (%s)\n", nt_errstr(status));
7836                 goto out;
7837         }
7838
7839         /* Now open the file again for read only. */
7840         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7841         if (!NT_STATUS_IS_OK(status)) {
7842                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7843                 goto out;
7844         }
7845
7846         /* Now unlink while open. */
7847         status = cli_posix_unlink(cli1, fname);
7848         if (!NT_STATUS_IS_OK(status)) {
7849                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7850                 goto out;
7851         }
7852
7853         status = cli_close(cli1, fnum1);
7854         if (!NT_STATUS_IS_OK(status)) {
7855                 printf("close(2) failed (%s)\n", nt_errstr(status));
7856                 goto out;
7857         }
7858
7859         /* Ensure the file has gone. */
7860         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7861         if (NT_STATUS_IS_OK(status)) {
7862                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7863                 goto out;
7864         }
7865
7866         /* Create again to test open with O_TRUNC. */
7867         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7868         if (!NT_STATUS_IS_OK(status)) {
7869                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7870                 goto out;
7871         }
7872
7873         /* Test ftruncate - set file size. */
7874         status = cli_ftruncate(cli1, fnum1, 1000);
7875         if (!NT_STATUS_IS_OK(status)) {
7876                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7877                 goto out;
7878         }
7879
7880         /* Ensure st_size == 1000 */
7881         status = cli_posix_stat(cli1, fname, &sbuf);
7882         if (!NT_STATUS_IS_OK(status)) {
7883                 printf("stat failed (%s)\n", nt_errstr(status));
7884                 goto out;
7885         }
7886
7887         if (sbuf.st_ex_size != 1000) {
7888                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7889                 goto out;
7890         }
7891
7892         status = cli_close(cli1, fnum1);
7893         if (!NT_STATUS_IS_OK(status)) {
7894                 printf("close(2) failed (%s)\n", nt_errstr(status));
7895                 goto out;
7896         }
7897
7898         /* Re-open with O_TRUNC. */
7899         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7900         if (!NT_STATUS_IS_OK(status)) {
7901                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7902                 goto out;
7903         }
7904
7905         /* Ensure st_size == 0 */
7906         status = cli_posix_stat(cli1, fname, &sbuf);
7907         if (!NT_STATUS_IS_OK(status)) {
7908                 printf("stat failed (%s)\n", nt_errstr(status));
7909                 goto out;
7910         }
7911
7912         if (sbuf.st_ex_size != 0) {
7913                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7914                 goto out;
7915         }
7916
7917         status = cli_close(cli1, fnum1);
7918         if (!NT_STATUS_IS_OK(status)) {
7919                 printf("close failed (%s)\n", nt_errstr(status));
7920                 goto out;
7921         }
7922
7923         status = cli_posix_unlink(cli1, fname);
7924         if (!NT_STATUS_IS_OK(status)) {
7925                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7926                 goto out;
7927         }
7928
7929         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7930         if (!NT_STATUS_IS_OK(status)) {
7931                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7932                         dname, nt_errstr(status));
7933                 goto out;
7934         }
7935
7936         cli_close(cli1, fnum1);
7937
7938         /* What happens when we try and POSIX open a directory for write ? */
7939         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7940         if (NT_STATUS_IS_OK(status)) {
7941                 printf("POSIX open of directory %s succeeded, "
7942                        "should have failed.\n",
7943                        dname);
7944                 goto out;
7945         } else {
7946                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7947                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7948                         goto out;
7949                 }
7950         }
7951
7952         /* Create the file. */
7953         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7954                                 0600, &fnum1);
7955         if (!NT_STATUS_IS_OK(status)) {
7956                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7957                 goto out;
7958         }
7959
7960         /* Write some data into it. */
7961         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7962                               NULL);
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("cli_write failed: %s\n", nt_errstr(status));
7965                 goto out;
7966         }
7967
7968         cli_close(cli1, fnum1);
7969
7970         /* Now create a hardlink. */
7971         status = cli_posix_hardlink(cli1, fname, hname);
7972         if (!NT_STATUS_IS_OK(status)) {
7973                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7974                 goto out;
7975         }
7976
7977         /* Now create a symlink. */
7978         status = cli_posix_symlink(cli1, fname, sname);
7979         if (!NT_STATUS_IS_OK(status)) {
7980                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7981                 goto out;
7982         }
7983
7984         /* Open the hardlink for read. */
7985         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7986         if (!NT_STATUS_IS_OK(status)) {
7987                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7988                 goto out;
7989         }
7990
7991         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7992         if (!NT_STATUS_IS_OK(status)) {
7993                 printf("POSIX read of %s failed (%s)\n", hname,
7994                        nt_errstr(status));
7995                 goto out;
7996         } else if (nread != 10) {
7997                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7998                        hname, (unsigned long)nread, 10);
7999                 goto out;
8000         }
8001
8002         if (memcmp(buf, "TEST DATA\n", 10)) {
8003                 printf("invalid data read from hardlink\n");
8004                 goto out;
8005         }
8006
8007         /* Do a POSIX lock/unlock. */
8008         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8009         if (!NT_STATUS_IS_OK(status)) {
8010                 printf("POSIX lock failed %s\n", nt_errstr(status));
8011                 goto out;
8012         }
8013
8014         /* Punch a hole in the locked area. */
8015         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8016         if (!NT_STATUS_IS_OK(status)) {
8017                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8018                 goto out;
8019         }
8020
8021         cli_close(cli1, fnum1);
8022
8023         /* Open the symlink for read - this should fail. A POSIX
8024            client should not be doing opens on a symlink. */
8025         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8026         if (NT_STATUS_IS_OK(status)) {
8027                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8028                 goto out;
8029         } else {
8030                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
8031                                 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8032                         printf("POSIX open of %s should have failed "
8033                                 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8034                                 "failed with %s instead.\n",
8035                                 sname, nt_errstr(status));
8036                         goto out;
8037                 }
8038         }
8039
8040         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
8041         if (!NT_STATUS_IS_OK(status)) {
8042                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8043                 goto out;
8044         }
8045
8046         if (strcmp(target, fname) != 0) {
8047                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8048                         sname, fname, target);
8049                 goto out;
8050         }
8051
8052         status = cli_posix_rmdir(cli1, dname);
8053         if (!NT_STATUS_IS_OK(status)) {
8054                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8055                 goto out;
8056         }
8057
8058         /* Check directory opens with a specific permission. */
8059         status = cli_posix_mkdir(cli1, dname, 0700);
8060         if (!NT_STATUS_IS_OK(status)) {
8061                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8062                 goto out;
8063         }
8064
8065         /* Ensure st_mode == 0700 */
8066         status = cli_posix_stat(cli1, dname, &sbuf);
8067         if (!NT_STATUS_IS_OK(status)) {
8068                 printf("stat failed (%s)\n", nt_errstr(status));
8069                 goto out;
8070         }
8071
8072         if ((sbuf.st_ex_mode & 07777) != 0700) {
8073                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8074                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8075                 goto out;
8076         }
8077
8078         /*
8079          * Now create a Windows file, and attempt a POSIX unlink.
8080          * This should fail with a sharing violation but due to:
8081          *
8082          * [Bug 9571] Unlink after open causes smbd to panic
8083          *
8084          * ensure we've fixed the lock ordering violation.
8085          */
8086
8087         status = cli_ntcreate(cli1, fname_windows, 0,
8088                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8089                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8090                         FILE_CREATE,
8091                         0x0, 0x0, &fnum2, NULL);
8092         if (!NT_STATUS_IS_OK(status)) {
8093                 printf("Windows create of %s failed (%s)\n", fname_windows,
8094                         nt_errstr(status));
8095                 goto out;
8096         }
8097
8098         /* Now try posix_unlink. */
8099         status = cli_posix_unlink(cli1, fname_windows);
8100         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8101                 printf("POSIX unlink of %s should fail "
8102                         "with NT_STATUS_SHARING_VIOLATION "
8103                         "got %s instead !\n",
8104                         fname_windows,
8105                         nt_errstr(status));
8106                 goto out;
8107         }
8108
8109         cli_close(cli1, fnum2);
8110
8111         printf("Simple POSIX open test passed\n");
8112         correct = true;
8113
8114   out:
8115
8116         if (fnum1 != (uint16_t)-1) {
8117                 cli_close(cli1, fnum1);
8118                 fnum1 = (uint16_t)-1;
8119         }
8120
8121         if (fnum2 != (uint16_t)-1) {
8122                 cli_close(cli1, fnum2);
8123                 fnum2 = (uint16_t)-1;
8124         }
8125
8126         cli_setatr(cli1, sname, 0, 0);
8127         cli_posix_unlink(cli1, sname);
8128         cli_setatr(cli1, hname, 0, 0);
8129         cli_posix_unlink(cli1, hname);
8130         cli_setatr(cli1, fname, 0, 0);
8131         cli_posix_unlink(cli1, fname);
8132         cli_setatr(cli1, dname, 0, 0);
8133         cli_posix_rmdir(cli1, dname);
8134         cli_setatr(cli1, fname_windows, 0, 0);
8135         cli_posix_unlink(cli1, fname_windows);
8136
8137         if (!torture_close_connection(cli1)) {
8138                 correct = false;
8139         }
8140
8141         return correct;
8142 }
8143
8144 /*
8145   Test POSIX and Windows ACLs are rejected on symlinks.
8146  */
8147 static bool run_acl_symlink_test(int dummy)
8148 {
8149         static struct cli_state *cli;
8150         const char *fname = "posix_file";
8151         const char *sname = "posix_symlink";
8152         uint16_t fnum = (uint16_t)-1;
8153         bool correct = false;
8154         NTSTATUS status;
8155         char *posix_acl = NULL;
8156         size_t posix_acl_len = 0;
8157         char *posix_acl_sym = NULL;
8158         size_t posix_acl_len_sym = 0;
8159         struct security_descriptor *sd = NULL;
8160         TALLOC_CTX *frame = NULL;
8161
8162         frame = talloc_stackframe();
8163
8164         printf("Starting acl symlink test\n");
8165
8166         if (!torture_open_connection(&cli, 0)) {
8167                 TALLOC_FREE(frame);
8168                 return false;
8169         }
8170
8171         smbXcli_conn_set_sockopt(cli->conn, sockops);
8172
8173         status = torture_setup_unix_extensions(cli);
8174         if (!NT_STATUS_IS_OK(status)) {
8175                 TALLOC_FREE(frame);
8176                 return false;
8177         }
8178
8179         cli_setatr(cli, fname, 0, 0);
8180         cli_posix_unlink(cli, fname);
8181         cli_setatr(cli, sname, 0, 0);
8182         cli_posix_unlink(cli, sname);
8183
8184         status = cli_ntcreate(cli,
8185                         fname,
8186                         0,
8187                         READ_CONTROL_ACCESS,
8188                         0,
8189                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8190                         FILE_CREATE,
8191                         0x0,
8192                         0x0,
8193                         &fnum,
8194                         NULL);
8195
8196         if (!NT_STATUS_IS_OK(status)) {
8197                 printf("cli_ntcreate of %s failed (%s)\n",
8198                         fname,
8199                         nt_errstr(status));
8200                 goto out;
8201         }
8202
8203         /* Get the Windows ACL on the file. */
8204         status = cli_query_secdesc(cli,
8205                                 fnum,
8206                                 frame,
8207                                 &sd);
8208         if (!NT_STATUS_IS_OK(status)) {
8209                 printf("cli_query_secdesc failed (%s)\n",
8210                         nt_errstr(status));
8211                 goto out;
8212         }
8213
8214         /* Get the POSIX ACL on the file. */
8215         status = cli_posix_getacl(cli,
8216                                 fname,
8217                                 frame,
8218                                 &posix_acl_len,
8219                                 &posix_acl);
8220
8221         if (!NT_STATUS_IS_OK(status)) {
8222                 printf("cli_posix_getacl failed (%s)\n",
8223                         nt_errstr(status));
8224                 goto out;
8225         }
8226
8227         status = cli_close(cli, fnum);
8228         if (!NT_STATUS_IS_OK(status)) {
8229                 printf("close failed (%s)\n", nt_errstr(status));
8230                 goto out;
8231         }
8232         fnum = (uint16_t)-1;
8233
8234         /* Now create a symlink. */
8235         status = cli_posix_symlink(cli, fname, sname);
8236         if (!NT_STATUS_IS_OK(status)) {
8237                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8238                         sname,
8239                         fname,
8240                         nt_errstr(status));
8241                 goto out;
8242         }
8243
8244         /* Open a handle on the symlink for SD set/get should fail. */
8245         status = cli_ntcreate(cli,
8246                         sname,
8247                         0,
8248                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8249                         0,
8250                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8251                         FILE_OPEN,
8252                         0x0,
8253                         0x0,
8254                         &fnum,
8255                         NULL);
8256
8257         if (NT_STATUS_IS_OK(status)) {
8258                 printf("Symlink open for getsd/setsd of %s "
8259                         "succeeded (should fail)\n",
8260                         sname);
8261                 goto out;
8262         }
8263
8264         /* Try a stat-open on the symlink, should also fail. */
8265         status = cli_ntcreate(cli,
8266                         sname,
8267                         0,
8268                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8269                         0,
8270                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8271                         FILE_OPEN,
8272                         0x0,
8273                         0x0,
8274                         &fnum,
8275                         NULL);
8276
8277         if (NT_STATUS_IS_OK(status)) {
8278                 printf("Stat-open of symlink succeeded (should fail)\n");
8279                 goto out;
8280         }
8281
8282         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8283         status = cli_posix_getacl(cli,
8284                                 sname,
8285                                 frame,
8286                                 &posix_acl_len_sym,
8287                                 &posix_acl_sym);
8288
8289         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8290                 printf("cli_posix_getacl on a symlink gave %s. "
8291                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8292                         nt_errstr(status));
8293                 goto out;
8294         }
8295
8296         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8297         status = cli_posix_setacl(cli,
8298                                 sname,
8299                                 posix_acl,
8300                                 posix_acl_len);
8301
8302         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8303                 printf("cli_posix_setacl on a symlink gave %s. "
8304                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8305                         nt_errstr(status));
8306                 goto out;
8307         }
8308
8309         printf("ACL symlink test passed\n");
8310         correct = true;
8311
8312   out:
8313
8314         if (fnum != (uint16_t)-1) {
8315                 cli_close(cli, fnum);
8316                 fnum = (uint16_t)-1;
8317         }
8318
8319         cli_setatr(cli, sname, 0, 0);
8320         cli_posix_unlink(cli, sname);
8321         cli_setatr(cli, fname, 0, 0);
8322         cli_posix_unlink(cli, fname);
8323
8324         if (!torture_close_connection(cli)) {
8325                 correct = false;
8326         }
8327
8328         TALLOC_FREE(frame);
8329         return correct;
8330 }
8331
8332 /*
8333   Test POSIX can delete a file containing streams.
8334  */
8335 static bool run_posix_stream_delete(int dummy)
8336 {
8337         struct cli_state *cli1 = NULL;
8338         struct cli_state *cli2 = NULL;
8339         const char *fname = "streamfile";
8340         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8341         uint16_t fnum1 = (uint16_t)-1;
8342         bool correct = false;
8343         NTSTATUS status;
8344         TALLOC_CTX *frame = NULL;
8345
8346         frame = talloc_stackframe();
8347
8348         printf("Starting POSIX stream delete test\n");
8349
8350         if (!torture_open_connection(&cli1, 0) ||
8351                         !torture_open_connection(&cli2, 1)) {
8352                 TALLOC_FREE(frame);
8353                 return false;
8354         }
8355
8356         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8357         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8358
8359         status = torture_setup_unix_extensions(cli2);
8360         if (!NT_STATUS_IS_OK(status)) {
8361                 goto out;
8362         }
8363
8364         cli_setatr(cli1, fname, 0, 0);
8365         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8366
8367         /* Create the file. */
8368         status = cli_ntcreate(cli1,
8369                         fname,
8370                         0,
8371                         READ_CONTROL_ACCESS,
8372                         0,
8373                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8374                         FILE_CREATE,
8375                         0x0,
8376                         0x0,
8377                         &fnum1,
8378                         NULL);
8379
8380         if (!NT_STATUS_IS_OK(status)) {
8381                 printf("cli_ntcreate of %s failed (%s)\n",
8382                         fname,
8383                         nt_errstr(status));
8384                 goto out;
8385         }
8386
8387         status = cli_close(cli1, fnum1);
8388         if (!NT_STATUS_IS_OK(status)) {
8389                 printf("cli_close of %s failed (%s)\n",
8390                         fname,
8391                         nt_errstr(status));
8392                 goto out;
8393         }
8394         fnum1 = (uint16_t)-1;
8395
8396         /* Now create the stream. */
8397         status = cli_ntcreate(cli1,
8398                         stream_fname,
8399                         0,
8400                         FILE_WRITE_DATA,
8401                         0,
8402                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8403                         FILE_CREATE,
8404                         0x0,
8405                         0x0,
8406                         &fnum1,
8407                         NULL);
8408
8409         if (!NT_STATUS_IS_OK(status)) {
8410                 printf("cli_ntcreate of %s failed (%s)\n",
8411                         stream_fname,
8412                         nt_errstr(status));
8413                 goto out;
8414         }
8415
8416         /* Leave the stream handle open... */
8417
8418         /* POSIX unlink should fail. */
8419         status = cli_posix_unlink(cli2, fname);
8420         if (NT_STATUS_IS_OK(status)) {
8421                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8422                         fname);
8423                 goto out;
8424         }
8425
8426         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8427                 printf("cli_posix_unlink of %s failed with (%s) "
8428                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8429                         fname,
8430                         nt_errstr(status));
8431                 goto out;
8432         }
8433
8434         /* Close the stream handle. */
8435         status = cli_close(cli1, fnum1);
8436         if (!NT_STATUS_IS_OK(status)) {
8437                 printf("cli_close of %s failed (%s)\n",
8438                         stream_fname,
8439                         nt_errstr(status));
8440                 goto out;
8441         }
8442         fnum1 = (uint16_t)-1;
8443
8444         /* POSIX unlink after stream handle closed should succeed. */
8445         status = cli_posix_unlink(cli2, fname);
8446         if (!NT_STATUS_IS_OK(status)) {
8447                 printf("cli_posix_unlink of %s failed (%s)\n",
8448                         fname,
8449                         nt_errstr(status));
8450                 goto out;
8451         }
8452
8453         printf("POSIX stream delete test passed\n");
8454         correct = true;
8455
8456   out:
8457
8458         if (fnum1 != (uint16_t)-1) {
8459                 cli_close(cli1, fnum1);
8460                 fnum1 = (uint16_t)-1;
8461         }
8462
8463         cli_setatr(cli1, fname, 0, 0);
8464         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8465
8466         if (!torture_close_connection(cli1)) {
8467                 correct = false;
8468         }
8469         if (!torture_close_connection(cli2)) {
8470                 correct = false;
8471         }
8472
8473         TALLOC_FREE(frame);
8474         return correct;
8475 }
8476
8477 /*
8478   Test setting EA's are rejected on symlinks.
8479  */
8480 static bool run_ea_symlink_test(int dummy)
8481 {
8482         static struct cli_state *cli;
8483         const char *fname = "posix_file_ea";
8484         const char *sname = "posix_symlink_ea";
8485         const char *ea_name = "testea_name";
8486         const char *ea_value = "testea_value";
8487         uint16_t fnum = (uint16_t)-1;
8488         bool correct = false;
8489         NTSTATUS status;
8490         size_t i, num_eas;
8491         struct ea_struct *eas = NULL;
8492         TALLOC_CTX *frame = NULL;
8493
8494         frame = talloc_stackframe();
8495
8496         printf("Starting EA symlink test\n");
8497
8498         if (!torture_open_connection(&cli, 0)) {
8499                 TALLOC_FREE(frame);
8500                 return false;
8501         }
8502
8503         smbXcli_conn_set_sockopt(cli->conn, sockops);
8504
8505         status = torture_setup_unix_extensions(cli);
8506         if (!NT_STATUS_IS_OK(status)) {
8507                 TALLOC_FREE(frame);
8508                 return false;
8509         }
8510
8511         cli_setatr(cli, fname, 0, 0);
8512         cli_posix_unlink(cli, fname);
8513         cli_setatr(cli, sname, 0, 0);
8514         cli_posix_unlink(cli, sname);
8515
8516         status = cli_ntcreate(cli,
8517                         fname,
8518                         0,
8519                         READ_CONTROL_ACCESS,
8520                         0,
8521                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8522                         FILE_CREATE,
8523                         0x0,
8524                         0x0,
8525                         &fnum,
8526                         NULL);
8527
8528         if (!NT_STATUS_IS_OK(status)) {
8529                 printf("cli_ntcreate of %s failed (%s)\n",
8530                         fname,
8531                         nt_errstr(status));
8532                 goto out;
8533         }
8534
8535         status = cli_close(cli, fnum);
8536         if (!NT_STATUS_IS_OK(status)) {
8537                 printf("close failed (%s)\n",
8538                         nt_errstr(status));
8539                 goto out;
8540         }
8541         fnum = (uint16_t)-1;
8542
8543         /* Set an EA on the path. */
8544         status = cli_set_ea_path(cli,
8545                                 fname,
8546                                 ea_name,
8547                                 ea_value,
8548                                 strlen(ea_value)+1);
8549
8550         if (!NT_STATUS_IS_OK(status)) {
8551                 printf("cli_set_ea_path failed (%s)\n",
8552                         nt_errstr(status));
8553                 goto out;
8554         }
8555
8556         /* Now create a symlink. */
8557         status = cli_posix_symlink(cli, fname, sname);
8558         if (!NT_STATUS_IS_OK(status)) {
8559                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8560                         sname,
8561                         fname,
8562                         nt_errstr(status));
8563                 goto out;
8564         }
8565
8566         /* Get the EA list on the path. Should return value set. */
8567         status = cli_get_ea_list_path(cli,
8568                                 fname,
8569                                 frame,
8570                                 &num_eas,
8571                                 &eas);
8572
8573         if (!NT_STATUS_IS_OK(status)) {
8574                 printf("cli_get_ea_list_path failed (%s)\n",
8575                         nt_errstr(status));
8576                 goto out;
8577         }
8578
8579         /* Ensure the EA we set is there. */
8580         for (i=0; i<num_eas; i++) {
8581                 if (strcmp(eas[i].name, ea_name) == 0 &&
8582                                 eas[i].value.length == strlen(ea_value)+1 &&
8583                                 memcmp(eas[i].value.data,
8584                                         ea_value,
8585                                         eas[i].value.length) == 0) {
8586                         break;
8587                 }
8588         }
8589
8590         if (i == num_eas) {
8591                 printf("Didn't find EA on pathname %s\n",
8592                         fname);
8593                 goto out;
8594         }
8595
8596         num_eas = 0;
8597         TALLOC_FREE(eas);
8598
8599         /* Get the EA list on the symlink. Should return empty list. */
8600         status = cli_get_ea_list_path(cli,
8601                                 sname,
8602                                 frame,
8603                                 &num_eas,
8604                                 &eas);
8605
8606         if (!NT_STATUS_IS_OK(status)) {
8607                 printf("cli_get_ea_list_path failed (%s)\n",
8608                         nt_errstr(status));
8609                 goto out;
8610         }
8611
8612         if (num_eas != 0) {
8613                 printf("cli_get_ea_list_path failed (%s)\n",
8614                         nt_errstr(status));
8615                 goto out;
8616         }
8617
8618         /* Set an EA on the symlink. Should fail. */
8619         status = cli_set_ea_path(cli,
8620                                 sname,
8621                                 ea_name,
8622                                 ea_value,
8623                                 strlen(ea_value)+1);
8624
8625         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8626                 printf("cli_set_ea_path on a symlink gave %s. "
8627                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8628                         nt_errstr(status));
8629                 goto out;
8630         }
8631
8632         printf("EA symlink test passed\n");
8633         correct = true;
8634
8635   out:
8636
8637         if (fnum != (uint16_t)-1) {
8638                 cli_close(cli, fnum);
8639                 fnum = (uint16_t)-1;
8640         }
8641
8642         cli_setatr(cli, sname, 0, 0);
8643         cli_posix_unlink(cli, sname);
8644         cli_setatr(cli, fname, 0, 0);
8645         cli_posix_unlink(cli, fname);
8646
8647         if (!torture_close_connection(cli)) {
8648                 correct = false;
8649         }
8650
8651         TALLOC_FREE(frame);
8652         return correct;
8653 }
8654
8655 /*
8656   Test POSIX locks are OFD-locks.
8657  */
8658 static bool run_posix_ofd_lock_test(int dummy)
8659 {
8660         static struct cli_state *cli;
8661         const char *fname = "posix_file";
8662         uint16_t fnum1 = (uint16_t)-1;
8663         uint16_t fnum2 = (uint16_t)-1;
8664         bool correct = false;
8665         NTSTATUS status;
8666         TALLOC_CTX *frame = NULL;
8667
8668         frame = talloc_stackframe();
8669
8670         printf("Starting POSIX ofd-lock test\n");
8671
8672         if (!torture_open_connection(&cli, 0)) {
8673                 TALLOC_FREE(frame);
8674                 return false;
8675         }
8676
8677         smbXcli_conn_set_sockopt(cli->conn, sockops);
8678
8679         status = torture_setup_unix_extensions(cli);
8680         if (!NT_STATUS_IS_OK(status)) {
8681                 TALLOC_FREE(frame);
8682                 return false;
8683         }
8684
8685         cli_setatr(cli, fname, 0, 0);
8686         cli_posix_unlink(cli, fname);
8687
8688         /* Open the file twice. */
8689         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8690                                 0600, &fnum1);
8691         if (!NT_STATUS_IS_OK(status)) {
8692                 printf("First POSIX open of %s failed\n", fname);
8693                 goto out;
8694         }
8695
8696         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8697         if (!NT_STATUS_IS_OK(status)) {
8698                 printf("First POSIX open of %s failed\n", fname);
8699                 goto out;
8700         }
8701
8702         /* Set a 0-50 lock on fnum1. */
8703         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8704         if (!NT_STATUS_IS_OK(status)) {
8705                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8706                 goto out;
8707         }
8708
8709         /* Set a 60-100 lock on fnum2. */
8710         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8711         if (!NT_STATUS_IS_OK(status)) {
8712                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8713                 goto out;
8714         }
8715
8716         /* close fnum1 - 0-50 lock should go away. */
8717         status = cli_close(cli, fnum1);
8718         if (!NT_STATUS_IS_OK(status)) {
8719                 printf("close failed (%s)\n",
8720                         nt_errstr(status));
8721                 goto out;
8722         }
8723         fnum1 = (uint16_t)-1;
8724
8725         /* Change the lock context. */
8726         cli_setpid(cli, cli_getpid(cli) + 1);
8727
8728         /* Re-open fnum1. */
8729         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8730         if (!NT_STATUS_IS_OK(status)) {
8731                 printf("Third POSIX open of %s failed\n", fname);
8732                 goto out;
8733         }
8734
8735         /* 60-100 lock should still be there. */
8736         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8737         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8738                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8739                 goto out;
8740         }
8741
8742         /* 0-50 lock should be gone. */
8743         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8744         if (!NT_STATUS_IS_OK(status)) {
8745                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8746                 goto out;
8747         }
8748
8749         printf("POSIX OFD lock test passed\n");
8750         correct = true;
8751
8752   out:
8753
8754         if (fnum1 != (uint16_t)-1) {
8755                 cli_close(cli, fnum1);
8756                 fnum1 = (uint16_t)-1;
8757         }
8758         if (fnum2 != (uint16_t)-1) {
8759                 cli_close(cli, fnum2);
8760                 fnum2 = (uint16_t)-1;
8761         }
8762
8763         cli_setatr(cli, fname, 0, 0);
8764         cli_posix_unlink(cli, fname);
8765
8766         if (!torture_close_connection(cli)) {
8767                 correct = false;
8768         }
8769
8770         TALLOC_FREE(frame);
8771         return correct;
8772 }
8773
8774 struct posix_blocking_state {
8775         struct tevent_context *ev;
8776         struct cli_state *cli1;
8777         uint16_t fnum1;
8778         struct cli_state *cli2;
8779         uint16_t fnum2;
8780         bool gotblocked;
8781         bool gotecho;
8782 };
8783
8784 static void posix_blocking_locked(struct tevent_req *subreq);
8785 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8786 static void posix_blocking_gotecho(struct tevent_req *subreq);
8787 static void posix_blocking_unlocked(struct tevent_req *subreq);
8788
8789 static struct tevent_req *posix_blocking_send(
8790         TALLOC_CTX *mem_ctx,
8791         struct tevent_context *ev,
8792         struct cli_state *cli1,
8793         uint16_t fnum1,
8794         struct cli_state *cli2,
8795         uint16_t fnum2)
8796 {
8797         struct tevent_req *req = NULL, *subreq = NULL;
8798         struct posix_blocking_state *state = NULL;
8799
8800         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8801         if (req == NULL) {
8802                 return NULL;
8803         }
8804         state->ev = ev;
8805         state->cli1 = cli1;
8806         state->fnum1 = fnum1;
8807         state->cli2 = cli2;
8808         state->fnum2 = fnum2;
8809
8810         subreq = cli_posix_lock_send(
8811                 state,
8812                 state->ev,
8813                 state->cli1,
8814                 state->fnum1,
8815                 0,
8816                 1,
8817                 false,
8818                 WRITE_LOCK);
8819         if (tevent_req_nomem(subreq, req)) {
8820                 return tevent_req_post(req, ev);
8821         }
8822         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8823         return req;
8824 }
8825
8826 static void posix_blocking_locked(struct tevent_req *subreq)
8827 {
8828         struct tevent_req *req = tevent_req_callback_data(
8829                 subreq, struct tevent_req);
8830         struct posix_blocking_state *state = tevent_req_data(
8831                 req, struct posix_blocking_state);
8832         NTSTATUS status;
8833
8834         status = cli_posix_lock_recv(subreq);
8835         TALLOC_FREE(subreq);
8836         if (tevent_req_nterror(req, status)) {
8837                 return;
8838         }
8839
8840         subreq = cli_posix_lock_send(
8841                 state,
8842                 state->ev,
8843                 state->cli2,
8844                 state->fnum2,
8845                 0,
8846                 1,
8847                 true,
8848                 WRITE_LOCK);
8849         if (tevent_req_nomem(subreq, req)) {
8850                 return;
8851         }
8852         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8853
8854         /* Make sure the blocking request is delivered */
8855         subreq = cli_echo_send(
8856                 state,
8857                 state->ev,
8858                 state->cli2,
8859                 1,
8860                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8861         if (tevent_req_nomem(subreq, req)) {
8862                 return;
8863         }
8864         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8865 }
8866
8867 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8868 {
8869         struct tevent_req *req = tevent_req_callback_data(
8870                 subreq, struct tevent_req);
8871         struct posix_blocking_state *state = tevent_req_data(
8872                 req, struct posix_blocking_state);
8873         NTSTATUS status;
8874
8875         status = cli_posix_lock_recv(subreq);
8876         TALLOC_FREE(subreq);
8877         if (tevent_req_nterror(req, status)) {
8878                 return;
8879         }
8880         if (!state->gotecho) {
8881                 printf("blocked req got through before echo\n");
8882                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8883                 return;
8884         }
8885         tevent_req_done(req);
8886 }
8887
8888 static void posix_blocking_gotecho(struct tevent_req *subreq)
8889 {
8890         struct tevent_req *req = tevent_req_callback_data(
8891                 subreq, struct tevent_req);
8892         struct posix_blocking_state *state = tevent_req_data(
8893                 req, struct posix_blocking_state);
8894         NTSTATUS status;
8895
8896         status = cli_echo_recv(subreq);
8897         TALLOC_FREE(subreq);
8898         if (tevent_req_nterror(req, status)) {
8899                 return;
8900         }
8901         if (state->gotblocked) {
8902                 printf("blocked req got through before echo\n");
8903                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8904                 return;
8905         }
8906         state->gotecho = true;
8907
8908         subreq = cli_posix_lock_send(
8909                 state,
8910                 state->ev,
8911                 state->cli1,
8912                 state->fnum1,
8913                 0,
8914                 1,
8915                 false,
8916                 UNLOCK_LOCK);
8917         if (tevent_req_nomem(subreq, req)) {
8918                 return;
8919         }
8920         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8921 }
8922
8923 static void posix_blocking_unlocked(struct tevent_req *subreq)
8924 {
8925         struct tevent_req *req = tevent_req_callback_data(
8926                 subreq, struct tevent_req);
8927         NTSTATUS status;
8928
8929         status = cli_posix_lock_recv(subreq);
8930         TALLOC_FREE(subreq);
8931         if (tevent_req_nterror(req, status)) {
8932                 return;
8933         }
8934         /* tevent_req_done in posix_blocking_gotlocked */
8935 }
8936
8937 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8938 {
8939         return tevent_req_simple_recv_ntstatus(req);
8940 }
8941
8942 static bool run_posix_blocking_lock(int dummy)
8943 {
8944         struct tevent_context *ev = NULL;
8945         struct cli_state *cli1 = NULL, *cli2 = NULL;
8946         const char *fname = "posix_blocking";
8947         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8948         struct tevent_req *req = NULL;
8949         NTSTATUS status;
8950         bool ret = false;
8951         bool ok;
8952
8953         printf("Starting posix blocking lock test\n");
8954
8955         ev = samba_tevent_context_init(NULL);
8956         if (ev == NULL) {
8957                 return false;
8958         }
8959
8960         ok = torture_open_connection(&cli1, 0);
8961         if (!ok) {
8962                 goto fail;
8963         }
8964         ok = torture_open_connection(&cli2, 0);
8965         if (!ok) {
8966                 goto fail;
8967         }
8968
8969         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8970
8971         status = torture_setup_unix_extensions(cli1);
8972         if (!NT_STATUS_IS_OK(status)) {
8973                 return false;
8974         }
8975
8976         status = torture_setup_unix_extensions(cli2);
8977         if (!NT_STATUS_IS_OK(status)) {
8978                 return false;
8979         }
8980
8981         cli_setatr(cli1, fname, 0, 0);
8982         cli_posix_unlink(cli1, fname);
8983
8984         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8985                                 0600, &fnum1);
8986         if (!NT_STATUS_IS_OK(status)) {
8987                 printf("First POSIX open of %s failed: %s\n",
8988                        fname,
8989                        nt_errstr(status));
8990                 goto fail;
8991         }
8992
8993         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8994         if (!NT_STATUS_IS_OK(status)) {
8995                 printf("Second POSIX open of %s failed: %s\n",
8996                        fname,
8997                        nt_errstr(status));
8998                 goto fail;
8999         }
9000
9001         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9002         if (req == NULL) {
9003                 printf("cli_posix_blocking failed\n");
9004                 goto fail;
9005         }
9006
9007         ok = tevent_req_poll_ntstatus(req, ev, &status);
9008         if (!ok) {
9009                 printf("tevent_req_poll_ntstatus failed: %s\n",
9010                        nt_errstr(status));
9011                 goto fail;
9012         }
9013         status = posix_blocking_recv(req);
9014         TALLOC_FREE(req);
9015         if (!NT_STATUS_IS_OK(status)) {
9016                 printf("posix_blocking_recv returned %s\n",
9017                        nt_errstr(status));
9018                 goto fail;
9019         }
9020
9021         ret = true;
9022 fail:
9023
9024         if (fnum1 != UINT16_MAX) {
9025                 cli_close(cli1, fnum1);
9026                 fnum1 = UINT16_MAX;
9027         }
9028         if (fnum2 != UINT16_MAX) {
9029                 cli_close(cli2, fnum2);
9030                 fnum2 = UINT16_MAX;
9031         }
9032
9033         if (cli1 != NULL) {
9034                 cli_setatr(cli1, fname, 0, 0);
9035                 cli_posix_unlink(cli1, fname);
9036         }
9037
9038         ok = true;
9039
9040         if (cli1 != NULL) {
9041                 ok &= torture_close_connection(cli1);
9042                 cli1 = NULL;
9043         }
9044         if (cli2 != NULL) {
9045                 ok &= torture_close_connection(cli2);
9046                 cli2 = NULL;
9047         }
9048
9049         if (!ok) {
9050                 ret = false;
9051         }
9052         TALLOC_FREE(ev);
9053         return ret;
9054 }
9055
9056 /*
9057   Test POSIX mkdir is case-sensitive.
9058  */
9059 static bool run_posix_mkdir_test(int dummy)
9060 {
9061         static struct cli_state *cli;
9062         const char *fname_foo = "POSIX_foo";
9063         const char *fname_foo_Foo = "POSIX_foo/Foo";
9064         const char *fname_foo_foo = "POSIX_foo/foo";
9065         const char *fname_Foo = "POSIX_Foo";
9066         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9067         const char *fname_Foo_foo = "POSIX_Foo/foo";
9068         bool correct = false;
9069         NTSTATUS status;
9070         TALLOC_CTX *frame = NULL;
9071         uint16_t fnum = (uint16_t)-1;
9072
9073         frame = talloc_stackframe();
9074
9075         printf("Starting POSIX mkdir test\n");
9076
9077         if (!torture_open_connection(&cli, 0)) {
9078                 TALLOC_FREE(frame);
9079                 return false;
9080         }
9081
9082         smbXcli_conn_set_sockopt(cli->conn, sockops);
9083
9084         status = torture_setup_unix_extensions(cli);
9085         if (!NT_STATUS_IS_OK(status)) {
9086                 TALLOC_FREE(frame);
9087                 return false;
9088         }
9089
9090         cli_posix_rmdir(cli, fname_foo_foo);
9091         cli_posix_rmdir(cli, fname_foo_Foo);
9092         cli_posix_rmdir(cli, fname_foo);
9093
9094         cli_posix_rmdir(cli, fname_Foo_foo);
9095         cli_posix_rmdir(cli, fname_Foo_Foo);
9096         cli_posix_rmdir(cli, fname_Foo);
9097
9098         /*
9099          * Create a file POSIX_foo then try
9100          * and use it in a directory path by
9101          * doing mkdir POSIX_foo/bar.
9102          * The mkdir should fail with
9103          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9104          */
9105
9106         status = cli_posix_open(cli,
9107                         fname_foo,
9108                         O_RDWR|O_CREAT,
9109                         0666,
9110                         &fnum);
9111         if (!NT_STATUS_IS_OK(status)) {
9112                 printf("cli_posix_open of %s failed error %s\n",
9113                         fname_foo,
9114                         nt_errstr(status));
9115                 goto out;
9116         }
9117
9118         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9119         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9120                 printf("cli_posix_mkdir of %s should fail with "
9121                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9122                         "%s instead\n",
9123                         fname_foo_foo,
9124                         nt_errstr(status));
9125                 goto out;
9126         }
9127
9128         status = cli_close(cli, fnum);
9129         if (!NT_STATUS_IS_OK(status)) {
9130                 printf("cli_close failed %s\n", nt_errstr(status));
9131                 goto out;
9132         }
9133         fnum = (uint16_t)-1;
9134
9135         status = cli_posix_unlink(cli, fname_foo);
9136         if (!NT_STATUS_IS_OK(status)) {
9137                 printf("cli_posix_unlink of %s failed error %s\n",
9138                         fname_foo,
9139                         nt_errstr(status));
9140                 goto out;
9141         }
9142
9143         /*
9144          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9145          * posix_open, posix_unlink, on
9146          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9147          * not silently create POSIX_foo/foo.
9148          */
9149
9150         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9151         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9152                 printf("cli_posix_mkdir of %s should fail with "
9153                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9154                         "%s instead\n",
9155                         fname_foo_foo,
9156                         nt_errstr(status));
9157                 goto out;
9158         }
9159
9160         status = cli_posix_rmdir(cli, fname_foo_foo);
9161         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9162                 printf("cli_posix_rmdir of %s should fail with "
9163                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9164                         "%s instead\n",
9165                         fname_foo_foo,
9166                         nt_errstr(status));
9167                 goto out;
9168         }
9169
9170         status = cli_posix_open(cli,
9171                         fname_foo_foo,
9172                         O_RDWR|O_CREAT,
9173                         0666,
9174                         &fnum);
9175         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9176                 printf("cli_posix_open of %s should fail with "
9177                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9178                         "%s instead\n",
9179                         fname_foo_foo,
9180                         nt_errstr(status));
9181                 goto out;
9182         }
9183
9184         status = cli_posix_unlink(cli, fname_foo_foo);
9185         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9186                 printf("cli_posix_unlink of %s should fail with "
9187                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9188                         "%s instead\n",
9189                         fname_foo_foo,
9190                         nt_errstr(status));
9191                 goto out;
9192         }
9193
9194         status = cli_posix_mkdir(cli, fname_foo, 0777);
9195         if (!NT_STATUS_IS_OK(status)) {
9196                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9197                 goto out;
9198         }
9199
9200         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9201         if (!NT_STATUS_IS_OK(status)) {
9202                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9203                 goto out;
9204         }
9205
9206         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9207         if (!NT_STATUS_IS_OK(status)) {
9208                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9209                 goto out;
9210         }
9211
9212         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9213         if (!NT_STATUS_IS_OK(status)) {
9214                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9215                 goto out;
9216         }
9217
9218         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9219         if (!NT_STATUS_IS_OK(status)) {
9220                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9221                 goto out;
9222         }
9223
9224         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9225         if (!NT_STATUS_IS_OK(status)) {
9226                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9227                 goto out;
9228         }
9229
9230         printf("POSIX mkdir test passed\n");
9231         correct = true;
9232
9233   out:
9234
9235         if (fnum != (uint16_t)-1) {
9236                 cli_close(cli, fnum);
9237                 fnum = (uint16_t)-1;
9238         }
9239
9240         cli_posix_rmdir(cli, fname_foo_foo);
9241         cli_posix_rmdir(cli, fname_foo_Foo);
9242         cli_posix_rmdir(cli, fname_foo);
9243
9244         cli_posix_rmdir(cli, fname_Foo_foo);
9245         cli_posix_rmdir(cli, fname_Foo_Foo);
9246         cli_posix_rmdir(cli, fname_Foo);
9247
9248         if (!torture_close_connection(cli)) {
9249                 correct = false;
9250         }
9251
9252         TALLOC_FREE(frame);
9253         return correct;
9254 }
9255
9256 struct posix_acl_oplock_state {
9257         struct tevent_context *ev;
9258         struct cli_state *cli;
9259         bool *got_break;
9260         bool *acl_ret;
9261         NTSTATUS status;
9262 };
9263
9264 static void posix_acl_oplock_got_break(struct tevent_req *req)
9265 {
9266         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9267                 req, struct posix_acl_oplock_state);
9268         uint16_t fnum;
9269         uint8_t level;
9270         NTSTATUS status;
9271
9272         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9273         TALLOC_FREE(req);
9274         if (!NT_STATUS_IS_OK(status)) {
9275                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9276                        nt_errstr(status));
9277                 return;
9278         }
9279         *state->got_break = true;
9280
9281         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9282                                   NO_OPLOCK);
9283         if (req == NULL) {
9284                 printf("cli_oplock_ack_send failed\n");
9285                 return;
9286         }
9287 }
9288
9289 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9290 {
9291         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9292                 req, struct posix_acl_oplock_state);
9293         size_t ret_size = 0;
9294         char *ret_data = NULL;
9295
9296         state->status = cli_posix_getacl_recv(req,
9297                         state,
9298                         &ret_size,
9299                         &ret_data);
9300
9301         if (!NT_STATUS_IS_OK(state->status)) {
9302                 printf("cli_posix_getacl_recv returned %s\n",
9303                         nt_errstr(state->status));
9304         }
9305         *state->acl_ret = true;
9306 }
9307
9308 static bool run_posix_acl_oplock_test(int dummy)
9309 {
9310         struct tevent_context *ev;
9311         struct cli_state *cli1, *cli2;
9312         struct tevent_req *oplock_req, *getacl_req;
9313         const char *fname = "posix_acl_oplock";
9314         uint16_t fnum;
9315         int saved_use_oplocks = use_oplocks;
9316         NTSTATUS status;
9317         bool correct = true;
9318         bool got_break = false;
9319         bool acl_ret = false;
9320
9321         struct posix_acl_oplock_state *state;
9322
9323         printf("starting posix_acl_oplock test\n");
9324
9325         if (!torture_open_connection(&cli1, 0)) {
9326                 use_level_II_oplocks = false;
9327                 use_oplocks = saved_use_oplocks;
9328                 return false;
9329         }
9330
9331         if (!torture_open_connection(&cli2, 1)) {
9332                 use_level_II_oplocks = false;
9333                 use_oplocks = saved_use_oplocks;
9334                 return false;
9335         }
9336
9337         /* Setup posix on cli2 only. */
9338         status = torture_setup_unix_extensions(cli2);
9339         if (!NT_STATUS_IS_OK(status)) {
9340                 return false;
9341         }
9342
9343         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9344         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9345
9346         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9347
9348         /* Create the file on the Windows connection. */
9349         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9350                           &fnum);
9351         if (!NT_STATUS_IS_OK(status)) {
9352                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9353                 return false;
9354         }
9355
9356         status = cli_close(cli1, fnum);
9357         if (!NT_STATUS_IS_OK(status)) {
9358                 printf("close1 failed (%s)\n", nt_errstr(status));
9359                 return false;
9360         }
9361
9362         cli1->use_oplocks = true;
9363
9364         /* Open with oplock. */
9365         status = cli_ntcreate(cli1,
9366                         fname,
9367                         0,
9368                         FILE_READ_DATA,
9369                         FILE_ATTRIBUTE_NORMAL,
9370                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9371                         FILE_OPEN,
9372                         0,
9373                         0,
9374                         &fnum,
9375                         NULL);
9376
9377         if (!NT_STATUS_IS_OK(status)) {
9378                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9379                 return false;
9380         }
9381
9382         ev = samba_tevent_context_init(talloc_tos());
9383         if (ev == NULL) {
9384                 printf("tevent_context_init failed\n");
9385                 return false;
9386         }
9387
9388         state = talloc_zero(ev, struct posix_acl_oplock_state);
9389         if (state == NULL) {
9390                 printf("talloc failed\n");
9391                 return false;
9392         }
9393         state->ev = ev;
9394         state->cli = cli1;
9395         state->got_break = &got_break;
9396         state->acl_ret = &acl_ret;
9397
9398         oplock_req = cli_smb_oplock_break_waiter_send(
9399                 talloc_tos(), ev, cli1);
9400         if (oplock_req == NULL) {
9401                 printf("cli_smb_oplock_break_waiter_send failed\n");
9402                 return false;
9403         }
9404         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9405
9406         /* Get ACL on POSIX connection - should break oplock. */
9407         getacl_req = cli_posix_getacl_send(talloc_tos(),
9408                                 ev,
9409                                 cli2,
9410                                 fname);
9411         if (getacl_req == NULL) {
9412                 printf("cli_posix_getacl_send failed\n");
9413                 return false;
9414         }
9415         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9416
9417         while (!got_break || !acl_ret) {
9418                 int ret;
9419                 ret = tevent_loop_once(ev);
9420                 if (ret == -1) {
9421                         printf("tevent_loop_once failed: %s\n",
9422                                strerror(errno));
9423                         return false;
9424                 }
9425         }
9426
9427         if (!NT_STATUS_IS_OK(state->status)) {
9428                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9429                 correct = false;
9430         }
9431
9432         status = cli_close(cli1, fnum);
9433         if (!NT_STATUS_IS_OK(status)) {
9434                 printf("close2 failed (%s)\n", nt_errstr(status));
9435                 correct = false;
9436         }
9437
9438         status = cli_unlink(cli1,
9439                         fname,
9440                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9441         if (!NT_STATUS_IS_OK(status)) {
9442                 printf("unlink failed (%s)\n", nt_errstr(status));
9443                 correct = false;
9444         }
9445
9446         if (!torture_close_connection(cli1)) {
9447                 correct = false;
9448         }
9449         if (!torture_close_connection(cli2)) {
9450                 correct = false;
9451         }
9452
9453         if (!got_break) {
9454                 correct = false;
9455         }
9456
9457         printf("finished posix acl oplock test\n");
9458
9459         return correct;
9460 }
9461
9462 static bool run_posix_acl_shareroot_test(int dummy)
9463 {
9464         struct cli_state *cli;
9465         NTSTATUS status;
9466         bool correct = false;
9467         char *posix_acl = NULL;
9468         size_t posix_acl_len = 0;
9469         uint16_t num_file_acls = 0;
9470         uint16_t num_dir_acls = 0;
9471         uint16_t i;
9472         uint32_t expected_size = 0;
9473         bool got_user = false;
9474         bool got_group = false;
9475         bool got_other = false;
9476         TALLOC_CTX *frame = NULL;
9477
9478         frame = talloc_stackframe();
9479
9480         printf("starting posix_acl_shareroot test\n");
9481
9482         if (!torture_open_connection(&cli, 0)) {
9483                 TALLOC_FREE(frame);
9484                 return false;
9485         }
9486
9487         smbXcli_conn_set_sockopt(cli->conn, sockops);
9488
9489         status = torture_setup_unix_extensions(cli);
9490         if (!NT_STATUS_IS_OK(status)) {
9491                 printf("Failed to setup unix extensions\n");
9492                 goto out;
9493         }
9494
9495         /* Get the POSIX ACL on the root of the share. */
9496         status = cli_posix_getacl(cli,
9497                                 ".",
9498                                 frame,
9499                                 &posix_acl_len,
9500                                 &posix_acl);
9501
9502         if (!NT_STATUS_IS_OK(status)) {
9503                 printf("cli_posix_getacl of '.' failed (%s)\n",
9504                         nt_errstr(status));
9505                 goto out;
9506         }
9507
9508         if (posix_acl_len < 6 ||
9509                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9510                 printf("getfacl ., unknown POSIX acl version %u.\n",
9511                         (unsigned int)CVAL(posix_acl,0) );
9512                 goto out;
9513         }
9514
9515         num_file_acls = SVAL(posix_acl,2);
9516         num_dir_acls = SVAL(posix_acl,4);
9517         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9518                                 SMB_POSIX_ACL_ENTRY_SIZE*
9519                                 (num_file_acls+num_dir_acls);
9520
9521         if (posix_acl_len != expected_size) {
9522                 printf("incorrect POSIX acl buffer size "
9523                         "(should be %u, was %u).\n",
9524                         (unsigned int)expected_size,
9525                         (unsigned int)posix_acl_len);
9526                 goto out;
9527         }
9528
9529         /*
9530          * We don't need to know what the ACL's are
9531          * we just need to know we have at least 3
9532          * file entries (u,g,o).
9533          */
9534
9535         for (i = 0; i < num_file_acls; i++) {
9536                 unsigned char tagtype =
9537                         CVAL(posix_acl,
9538                                 SMB_POSIX_ACL_HEADER_SIZE+
9539                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9540
9541                 switch(tagtype) {
9542                         case SMB_POSIX_ACL_USER_OBJ:
9543                                 got_user = true;
9544                                 break;
9545                         case SMB_POSIX_ACL_GROUP_OBJ:
9546                                 got_group = true;
9547                                 break;
9548                         case SMB_POSIX_ACL_OTHER:
9549                                 got_other = true;
9550                                 break;
9551                         default:
9552                                 break;
9553                 }
9554         }
9555
9556         if (!got_user) {
9557                 printf("Missing user entry\n");
9558                 goto out;
9559         }
9560
9561         if (!got_group) {
9562                 printf("Missing group entry\n");
9563                 goto out;
9564         }
9565
9566         if (!got_other) {
9567                 printf("Missing other entry\n");
9568                 goto out;
9569         }
9570
9571         correct = true;
9572
9573   out:
9574
9575         if (!torture_close_connection(cli)) {
9576                 correct = false;
9577         }
9578
9579         printf("finished posix acl shareroot test\n");
9580         TALLOC_FREE(frame);
9581
9582         return correct;
9583 }
9584
9585 static uint32_t open_attrs_table[] = {
9586                 FILE_ATTRIBUTE_NORMAL,
9587                 FILE_ATTRIBUTE_ARCHIVE,
9588                 FILE_ATTRIBUTE_READONLY,
9589                 FILE_ATTRIBUTE_HIDDEN,
9590                 FILE_ATTRIBUTE_SYSTEM,
9591
9592                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9593                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9594                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9595                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9596                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9597                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9598
9599                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9600                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9601                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9602                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9603 };
9604
9605 struct trunc_open_results {
9606         unsigned int num;
9607         uint32_t init_attr;
9608         uint32_t trunc_attr;
9609         uint32_t result_attr;
9610 };
9611
9612 static struct trunc_open_results attr_results[] = {
9613         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9614         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9615         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9616         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9617         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9618         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9619         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9620         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9621         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9622         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9623         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9624         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9625         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9626         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9627         { 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 },
9628         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9629         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9630         { 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 },
9631         { 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 },
9632         { 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 },
9633         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9634         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9635         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9636         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9637         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9638         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9639 };
9640
9641 static bool run_openattrtest(int dummy)
9642 {
9643         static struct cli_state *cli1;
9644         const char *fname = "\\openattr.file";
9645         uint16_t fnum1;
9646         bool correct = True;
9647         uint32_t attr;
9648         unsigned int i, j, k, l;
9649         NTSTATUS status;
9650
9651         printf("starting open attr test\n");
9652
9653         if (!torture_open_connection(&cli1, 0)) {
9654                 return False;
9655         }
9656
9657         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9658
9659         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9660                 cli_setatr(cli1, fname, 0, 0);
9661                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9662
9663                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9664                                        open_attrs_table[i], FILE_SHARE_NONE,
9665                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9666                 if (!NT_STATUS_IS_OK(status)) {
9667                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9668                         return False;
9669                 }
9670
9671                 status = cli_close(cli1, fnum1);
9672                 if (!NT_STATUS_IS_OK(status)) {
9673                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9674                         return False;
9675                 }
9676
9677                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9678                         status = cli_ntcreate(cli1, fname, 0,
9679                                               FILE_READ_DATA|FILE_WRITE_DATA,
9680                                               open_attrs_table[j],
9681                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9682                                               0, 0, &fnum1, NULL);
9683                         if (!NT_STATUS_IS_OK(status)) {
9684                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9685                                         if (attr_results[l].num == k) {
9686                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9687                                                                 k, open_attrs_table[i],
9688                                                                 open_attrs_table[j],
9689                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9690                                                 correct = False;
9691                                         }
9692                                 }
9693
9694                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9695                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9696                                                         k, open_attrs_table[i], open_attrs_table[j],
9697                                                         nt_errstr(status));
9698                                         correct = False;
9699                                 }
9700 #if 0
9701                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9702 #endif
9703                                 k++;
9704                                 continue;
9705                         }
9706
9707                         status = cli_close(cli1, fnum1);
9708                         if (!NT_STATUS_IS_OK(status)) {
9709                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9710                                 return False;
9711                         }
9712
9713                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9714                         if (!NT_STATUS_IS_OK(status)) {
9715                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9716                                 return False;
9717                         }
9718
9719 #if 0
9720                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9721                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9722 #endif
9723
9724                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9725                                 if (attr_results[l].num == k) {
9726                                         if (attr != attr_results[l].result_attr ||
9727                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9728                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9729                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9730                                                 open_attrs_table[i],
9731                                                 open_attrs_table[j],
9732                                                 (unsigned int)attr,
9733                                                 attr_results[l].result_attr);
9734                                                 correct = False;
9735                                         }
9736                                         break;
9737                                 }
9738                         }
9739                         k++;
9740                 }
9741         }
9742
9743         cli_setatr(cli1, fname, 0, 0);
9744         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9745
9746         printf("open attr test %s.\n", correct ? "passed" : "failed");
9747
9748         if (!torture_close_connection(cli1)) {
9749                 correct = False;
9750         }
9751         return correct;
9752 }
9753
9754 static NTSTATUS list_fn(struct file_info *finfo,
9755                     const char *name, void *state)
9756 {
9757         int *matched = (int *)state;
9758         if (matched != NULL) {
9759                 *matched += 1;
9760         }
9761         return NT_STATUS_OK;
9762 }
9763
9764 /*
9765   test directory listing speed
9766  */
9767 static bool run_dirtest(int dummy)
9768 {
9769         int i;
9770         static struct cli_state *cli;
9771         uint16_t fnum;
9772         struct timeval core_start;
9773         bool correct = True;
9774         int matched;
9775
9776         printf("starting directory test\n");
9777
9778         if (!torture_open_connection(&cli, 0)) {
9779                 return False;
9780         }
9781
9782         smbXcli_conn_set_sockopt(cli->conn, sockops);
9783
9784         srandom(0);
9785         for (i=0;i<torture_numops;i++) {
9786                 fstring fname;
9787                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9788                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9789                         fprintf(stderr,"Failed to open %s\n", fname);
9790                         return False;
9791                 }
9792                 cli_close(cli, fnum);
9793         }
9794
9795         core_start = timeval_current();
9796
9797         matched = 0;
9798         cli_list(cli, "a*.*", 0, list_fn, &matched);
9799         printf("Matched %d\n", matched);
9800
9801         matched = 0;
9802         cli_list(cli, "b*.*", 0, list_fn, &matched);
9803         printf("Matched %d\n", matched);
9804
9805         matched = 0;
9806         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9807         printf("Matched %d\n", matched);
9808
9809         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9810
9811         srandom(0);
9812         for (i=0;i<torture_numops;i++) {
9813                 fstring fname;
9814                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9815                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9816         }
9817
9818         if (!torture_close_connection(cli)) {
9819                 correct = False;
9820         }
9821
9822         printf("finished dirtest\n");
9823
9824         return correct;
9825 }
9826
9827 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9828                    void *state)
9829 {
9830         struct cli_state *pcli = (struct cli_state *)state;
9831         fstring fname;
9832         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9833
9834         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9835                 return NT_STATUS_OK;
9836
9837         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9838                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9839                         printf("del_fn: failed to rmdir %s\n,", fname );
9840         } else {
9841                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9842                         printf("del_fn: failed to unlink %s\n,", fname );
9843         }
9844         return NT_STATUS_OK;
9845 }
9846
9847
9848 /*
9849   sees what IOCTLs are supported
9850  */
9851 bool torture_ioctl_test(int dummy)
9852 {
9853         static struct cli_state *cli;
9854         uint16_t device, function;
9855         uint16_t fnum;
9856         const char *fname = "\\ioctl.dat";
9857         DATA_BLOB blob;
9858         NTSTATUS status;
9859
9860         if (!torture_open_connection(&cli, 0)) {
9861                 return False;
9862         }
9863
9864         printf("starting ioctl test\n");
9865
9866         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9867
9868         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9869         if (!NT_STATUS_IS_OK(status)) {
9870                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9871                 return False;
9872         }
9873
9874         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9875         printf("ioctl device info: %s\n", nt_errstr(status));
9876
9877         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9878         printf("ioctl job info: %s\n", nt_errstr(status));
9879
9880         for (device=0;device<0x100;device++) {
9881                 printf("ioctl test with device = 0x%x\n", device);
9882                 for (function=0;function<0x100;function++) {
9883                         uint32_t code = (device<<16) | function;
9884
9885                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9886
9887                         if (NT_STATUS_IS_OK(status)) {
9888                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9889                                        (int)blob.length);
9890                                 data_blob_free(&blob);
9891                         }
9892                 }
9893         }
9894
9895         if (!torture_close_connection(cli)) {
9896                 return False;
9897         }
9898
9899         return True;
9900 }
9901
9902
9903 /*
9904   tries varients of chkpath
9905  */
9906 bool torture_chkpath_test(int dummy)
9907 {
9908         static struct cli_state *cli;
9909         uint16_t fnum;
9910         bool ret;
9911         NTSTATUS status;
9912
9913         if (!torture_open_connection(&cli, 0)) {
9914                 return False;
9915         }
9916
9917         printf("starting chkpath test\n");
9918
9919         /* cleanup from an old run */
9920         torture_deltree(cli, "\\chkpath.dir");
9921
9922         status = cli_mkdir(cli, "\\chkpath.dir");
9923         if (!NT_STATUS_IS_OK(status)) {
9924                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9925                 return False;
9926         }
9927
9928         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9929         if (!NT_STATUS_IS_OK(status)) {
9930                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9931                 return False;
9932         }
9933
9934         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9935                           DENY_NONE, &fnum);
9936         if (!NT_STATUS_IS_OK(status)) {
9937                 printf("open1 failed (%s)\n", nt_errstr(status));
9938                 return False;
9939         }
9940         cli_close(cli, fnum);
9941
9942         status = cli_chkpath(cli, "\\chkpath.dir");
9943         if (!NT_STATUS_IS_OK(status)) {
9944                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9945                 ret = False;
9946         }
9947
9948         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9949         if (!NT_STATUS_IS_OK(status)) {
9950                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9951                 ret = False;
9952         }
9953
9954         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9955         if (!NT_STATUS_IS_OK(status)) {
9956                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9957                                   NT_STATUS_NOT_A_DIRECTORY);
9958         } else {
9959                 printf("* chkpath on a file should fail\n");
9960                 ret = False;
9961         }
9962
9963         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9964         if (!NT_STATUS_IS_OK(status)) {
9965                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9966                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9967         } else {
9968                 printf("* chkpath on a non existent file should fail\n");
9969                 ret = False;
9970         }
9971
9972         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9973         if (!NT_STATUS_IS_OK(status)) {
9974                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9975                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9976         } else {
9977                 printf("* chkpath on a non existent component should fail\n");
9978                 ret = False;
9979         }
9980
9981         torture_deltree(cli, "\\chkpath.dir");
9982
9983         if (!torture_close_connection(cli)) {
9984                 return False;
9985         }
9986
9987         return ret;
9988 }
9989
9990 static bool run_eatest(int dummy)
9991 {
9992         static struct cli_state *cli;
9993         const char *fname = "\\eatest.txt";
9994         bool correct = True;
9995         uint16_t fnum;
9996         size_t i, num_eas;
9997         struct ea_struct *ea_list = NULL;
9998         TALLOC_CTX *mem_ctx = talloc_init("eatest");
9999         NTSTATUS status;
10000
10001         printf("starting eatest\n");
10002
10003         if (!torture_open_connection(&cli, 0)) {
10004                 talloc_destroy(mem_ctx);
10005                 return False;
10006         }
10007
10008         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10009
10010         status = cli_ntcreate(cli, fname, 0,
10011                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10012                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10013                               0x4044, 0, &fnum, NULL);
10014         if (!NT_STATUS_IS_OK(status)) {
10015                 printf("open failed - %s\n", nt_errstr(status));
10016                 talloc_destroy(mem_ctx);
10017                 return False;
10018         }
10019
10020         for (i = 0; i < 10; i++) {
10021                 fstring ea_name, ea_val;
10022
10023                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10024                 memset(ea_val, (char)i+1, i+1);
10025                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10026                 if (!NT_STATUS_IS_OK(status)) {
10027                         printf("ea_set of name %s failed - %s\n", ea_name,
10028                                nt_errstr(status));
10029                         talloc_destroy(mem_ctx);
10030                         return False;
10031                 }
10032         }
10033
10034         cli_close(cli, fnum);
10035         for (i = 0; i < 10; i++) {
10036                 fstring ea_name, ea_val;
10037
10038                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10039                 memset(ea_val, (char)i+1, i+1);
10040                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10041                 if (!NT_STATUS_IS_OK(status)) {
10042                         printf("ea_set of name %s failed - %s\n", ea_name,
10043                                nt_errstr(status));
10044                         talloc_destroy(mem_ctx);
10045                         return False;
10046                 }
10047         }
10048
10049         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10050         if (!NT_STATUS_IS_OK(status)) {
10051                 printf("ea_get list failed - %s\n", nt_errstr(status));
10052                 correct = False;
10053         }
10054
10055         printf("num_eas = %d\n", (int)num_eas);
10056
10057         if (num_eas != 20) {
10058                 printf("Should be 20 EA's stored... failing.\n");
10059                 correct = False;
10060         }
10061
10062         for (i = 0; i < num_eas; i++) {
10063                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10064                 dump_data(0, ea_list[i].value.data,
10065                           ea_list[i].value.length);
10066         }
10067
10068         /* Setting EA's to zero length deletes them. Test this */
10069         printf("Now deleting all EA's - case indepenent....\n");
10070
10071 #if 1
10072         cli_set_ea_path(cli, fname, "", "", 0);
10073 #else
10074         for (i = 0; i < 20; i++) {
10075                 fstring ea_name;
10076                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10077                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10078                 if (!NT_STATUS_IS_OK(status)) {
10079                         printf("ea_set of name %s failed - %s\n", ea_name,
10080                                nt_errstr(status));
10081                         talloc_destroy(mem_ctx);
10082                         return False;
10083                 }
10084         }
10085 #endif
10086
10087         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10088         if (!NT_STATUS_IS_OK(status)) {
10089                 printf("ea_get list failed - %s\n", nt_errstr(status));
10090                 correct = False;
10091         }
10092
10093         printf("num_eas = %d\n", (int)num_eas);
10094         for (i = 0; i < num_eas; i++) {
10095                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10096                 dump_data(0, ea_list[i].value.data,
10097                           ea_list[i].value.length);
10098         }
10099
10100         if (num_eas != 0) {
10101                 printf("deleting EA's failed.\n");
10102                 correct = False;
10103         }
10104
10105         /* Try and delete a non existent EA. */
10106         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10107         if (!NT_STATUS_IS_OK(status)) {
10108                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10109                        nt_errstr(status));
10110                 correct = False;
10111         }
10112
10113         talloc_destroy(mem_ctx);
10114         if (!torture_close_connection(cli)) {
10115                 correct = False;
10116         }
10117
10118         return correct;
10119 }
10120
10121 static bool run_dirtest1(int dummy)
10122 {
10123         int i;
10124         static struct cli_state *cli;
10125         uint16_t fnum;
10126         int num_seen;
10127         bool correct = True;
10128
10129         printf("starting directory test\n");
10130
10131         if (!torture_open_connection(&cli, 0)) {
10132                 return False;
10133         }
10134
10135         smbXcli_conn_set_sockopt(cli->conn, sockops);
10136
10137         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10138         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10139         cli_rmdir(cli, "\\LISTDIR");
10140         cli_mkdir(cli, "\\LISTDIR");
10141
10142         /* Create 1000 files and 1000 directories. */
10143         for (i=0;i<1000;i++) {
10144                 fstring fname;
10145                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10146                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10147                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10148                                    0, 0, &fnum, NULL))) {
10149                         fprintf(stderr,"Failed to open %s\n", fname);
10150                         return False;
10151                 }
10152                 cli_close(cli, fnum);
10153         }
10154         for (i=0;i<1000;i++) {
10155                 fstring fname;
10156                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10157                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10158                         fprintf(stderr,"Failed to open %s\n", fname);
10159                         return False;
10160                 }
10161         }
10162
10163         /* Now ensure that doing an old list sees both files and directories. */
10164         num_seen = 0;
10165         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10166         printf("num_seen = %d\n", num_seen );
10167         /* We should see 100 files + 1000 directories + . and .. */
10168         if (num_seen != 2002)
10169                 correct = False;
10170
10171         /* Ensure if we have the "must have" bits we only see the
10172          * relevent entries.
10173          */
10174         num_seen = 0;
10175         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10176         printf("num_seen = %d\n", num_seen );
10177         if (num_seen != 1002)
10178                 correct = False;
10179
10180         num_seen = 0;
10181         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10182         printf("num_seen = %d\n", num_seen );
10183         if (num_seen != 1000)
10184                 correct = False;
10185
10186         /* Delete everything. */
10187         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10188         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10189         cli_rmdir(cli, "\\LISTDIR");
10190
10191 #if 0
10192         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10193         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10194         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10195 #endif
10196
10197         if (!torture_close_connection(cli)) {
10198                 correct = False;
10199         }
10200
10201         printf("finished dirtest1\n");
10202
10203         return correct;
10204 }
10205
10206 static bool run_error_map_extract(int dummy) {
10207
10208         static struct cli_state *c_dos;
10209         static struct cli_state *c_nt;
10210         NTSTATUS status;
10211
10212         uint32_t error;
10213
10214         uint32_t errnum;
10215         uint8_t errclass;
10216
10217         NTSTATUS nt_status;
10218
10219         fstring user;
10220
10221         /* NT-Error connection */
10222
10223         disable_spnego = true;
10224         if (!(c_nt = open_nbt_connection())) {
10225                 disable_spnego = false;
10226                 return False;
10227         }
10228         disable_spnego = false;
10229
10230         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10231                                  PROTOCOL_NT1);
10232
10233         if (!NT_STATUS_IS_OK(status)) {
10234                 printf("%s rejected the NT-error negprot (%s)\n", host,
10235                        nt_errstr(status));
10236                 cli_shutdown(c_nt);
10237                 return False;
10238         }
10239
10240         status = cli_session_setup_anon(c_nt);
10241         if (!NT_STATUS_IS_OK(status)) {
10242                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10243                 return False;
10244         }
10245
10246         /* DOS-Error connection */
10247
10248         disable_spnego = true;
10249         force_dos_errors = true;
10250         if (!(c_dos = open_nbt_connection())) {
10251                 disable_spnego = false;
10252                 force_dos_errors = false;
10253                 return False;
10254         }
10255         disable_spnego = false;
10256         force_dos_errors = false;
10257
10258         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10259                                  PROTOCOL_NT1);
10260         if (!NT_STATUS_IS_OK(status)) {
10261                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10262                        nt_errstr(status));
10263                 cli_shutdown(c_dos);
10264                 return False;
10265         }
10266
10267         status = cli_session_setup_anon(c_dos);
10268         if (!NT_STATUS_IS_OK(status)) {
10269                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10270                         host, nt_errstr(status));
10271                 return False;
10272         }
10273
10274         c_nt->map_dos_errors = false;
10275         c_dos->map_dos_errors = false;
10276
10277         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10278                 struct cli_credentials *user_creds = NULL;
10279
10280                 fstr_sprintf(user, "%X", error);
10281
10282                 user_creds = cli_session_creds_init(talloc_tos(),
10283                                                     user,
10284                                                     workgroup,
10285                                                     NULL, /* realm */
10286                                                     password,
10287                                                     false, /* use_kerberos */
10288                                                     false, /* fallback_after_kerberos */
10289                                                     false, /* use_ccache */
10290                                                     false); /* password_is_nt_hash */
10291                 if (user_creds == NULL) {
10292                         printf("cli_session_creds_init(%s) failed\n", user);
10293                         return false;
10294                 }
10295
10296                 status = cli_session_setup_creds(c_nt, user_creds);
10297                 if (NT_STATUS_IS_OK(status)) {
10298                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10299                 }
10300
10301                 /* Case #1: 32-bit NT errors */
10302                 if (!NT_STATUS_IS_DOS(status)) {
10303                         nt_status = status;
10304                 } else {
10305                         printf("/** Dos error on NT connection! (%s) */\n", 
10306                                nt_errstr(status));
10307                         nt_status = NT_STATUS(0xc0000000);
10308                 }
10309
10310                 status = cli_session_setup_creds(c_dos, user_creds);
10311                 if (NT_STATUS_IS_OK(status)) {
10312                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10313                 }
10314
10315                 /* Case #1: 32-bit NT errors */
10316                 if (NT_STATUS_IS_DOS(status)) {
10317                         printf("/** NT error on DOS connection! (%s) */\n", 
10318                                nt_errstr(status));
10319                         errnum = errclass = 0;
10320                 } else {
10321                         errclass = NT_STATUS_DOS_CLASS(status);
10322                         errnum = NT_STATUS_DOS_CODE(status);
10323                 }
10324
10325                 if (NT_STATUS_V(nt_status) != error) { 
10326                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10327                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10328                                get_nt_error_c_code(talloc_tos(), nt_status));
10329                 }
10330
10331                 printf("\t{%s,\t%s,\t%s},\n", 
10332                        smb_dos_err_class(errclass), 
10333                        smb_dos_err_name(errclass, errnum), 
10334                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10335
10336                 TALLOC_FREE(user_creds);
10337         }
10338         return True;
10339 }
10340
10341 static bool run_sesssetup_bench(int dummy)
10342 {
10343         static struct cli_state *c;
10344         const char *fname = "\\file.dat";
10345         uint16_t fnum;
10346         NTSTATUS status;
10347         int i;
10348
10349         if (!torture_open_connection(&c, 0)) {
10350                 return false;
10351         }
10352
10353         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10354                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10355                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10356         if (!NT_STATUS_IS_OK(status)) {
10357                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10358                 return false;
10359         }
10360
10361         for (i=0; i<torture_numops; i++) {
10362                 status = cli_session_setup_creds(c, torture_creds);
10363                 if (!NT_STATUS_IS_OK(status)) {
10364                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10365                                  __location__, nt_errstr(status));
10366                         return false;
10367                 }
10368
10369                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10370
10371                 status = cli_ulogoff(c);
10372                 if (!NT_STATUS_IS_OK(status)) {
10373                         d_printf("(%s) cli_ulogoff failed: %s\n",
10374                                  __location__, nt_errstr(status));
10375                         return false;
10376                 }
10377         }
10378
10379         return true;
10380 }
10381
10382 static bool subst_test(const char *str, const char *user, const char *domain,
10383                        uid_t uid, gid_t gid, const char *expected)
10384 {
10385         char *subst;
10386         bool result = true;
10387
10388         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10389
10390         if (strcmp(subst, expected) != 0) {
10391                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10392                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10393                        expected);
10394                 result = false;
10395         }
10396
10397         TALLOC_FREE(subst);
10398         return result;
10399 }
10400
10401 static void chain1_open_completion(struct tevent_req *req)
10402 {
10403         uint16_t fnum;
10404         NTSTATUS status;
10405         status = cli_openx_recv(req, &fnum);
10406         TALLOC_FREE(req);
10407
10408         d_printf("cli_openx_recv returned %s: %d\n",
10409                  nt_errstr(status),
10410                  NT_STATUS_IS_OK(status) ? fnum : -1);
10411 }
10412
10413 static void chain1_write_completion(struct tevent_req *req)
10414 {
10415         size_t written;
10416         NTSTATUS status;
10417         status = cli_write_andx_recv(req, &written);
10418         TALLOC_FREE(req);
10419
10420         d_printf("cli_write_andx_recv returned %s: %d\n",
10421                  nt_errstr(status),
10422                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10423 }
10424
10425 static void chain1_close_completion(struct tevent_req *req)
10426 {
10427         NTSTATUS status;
10428         bool *done = (bool *)tevent_req_callback_data_void(req);
10429
10430         status = cli_close_recv(req);
10431         *done = true;
10432
10433         TALLOC_FREE(req);
10434
10435         d_printf("cli_close returned %s\n", nt_errstr(status));
10436 }
10437
10438 static bool run_chain1(int dummy)
10439 {
10440         struct cli_state *cli1;
10441         struct tevent_context *evt = samba_tevent_context_init(NULL);
10442         struct tevent_req *reqs[3], *smbreqs[3];
10443         bool done = false;
10444         const char *str = "foobar";
10445         const char *fname = "\\test_chain";
10446         NTSTATUS status;
10447
10448         printf("starting chain1 test\n");
10449         if (!torture_open_connection(&cli1, 0)) {
10450                 return False;
10451         }
10452
10453         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10454
10455         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10456
10457         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10458                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10459         if (reqs[0] == NULL) return false;
10460         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10461
10462
10463         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10464                                         (const uint8_t *)str, 0, strlen(str)+1,
10465                                         smbreqs, 1, &smbreqs[1]);
10466         if (reqs[1] == NULL) return false;
10467         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10468
10469         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10470         if (reqs[2] == NULL) return false;
10471         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10472
10473         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10474         if (!NT_STATUS_IS_OK(status)) {
10475                 return false;
10476         }
10477
10478         while (!done) {
10479                 tevent_loop_once(evt);
10480         }
10481
10482         torture_close_connection(cli1);
10483         return True;
10484 }
10485
10486 static void chain2_sesssetup_completion(struct tevent_req *req)
10487 {
10488         NTSTATUS status;
10489         status = cli_session_setup_guest_recv(req);
10490         d_printf("sesssetup returned %s\n", nt_errstr(status));
10491 }
10492
10493 static void chain2_tcon_completion(struct tevent_req *req)
10494 {
10495         bool *done = (bool *)tevent_req_callback_data_void(req);
10496         NTSTATUS status;
10497         status = cli_tcon_andx_recv(req);
10498         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10499         *done = true;
10500 }
10501
10502 static bool run_chain2(int dummy)
10503 {
10504         struct cli_state *cli1;
10505         struct tevent_context *evt = samba_tevent_context_init(NULL);
10506         struct tevent_req *reqs[2], *smbreqs[2];
10507         bool done = false;
10508         NTSTATUS status;
10509         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10510
10511         printf("starting chain2 test\n");
10512         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10513                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10514         if (!NT_STATUS_IS_OK(status)) {
10515                 return False;
10516         }
10517
10518         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10519
10520         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10521                                                  &smbreqs[0]);
10522         if (reqs[0] == NULL) return false;
10523         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10524
10525         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10526                                        "?????", NULL, 0, &smbreqs[1]);
10527         if (reqs[1] == NULL) return false;
10528         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10529
10530         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10531         if (!NT_STATUS_IS_OK(status)) {
10532                 return false;
10533         }
10534
10535         while (!done) {
10536                 tevent_loop_once(evt);
10537         }
10538
10539         torture_close_connection(cli1);
10540         return True;
10541 }
10542
10543
10544 struct torture_createdel_state {
10545         struct tevent_context *ev;
10546         struct cli_state *cli;
10547 };
10548
10549 static void torture_createdel_created(struct tevent_req *subreq);
10550 static void torture_createdel_closed(struct tevent_req *subreq);
10551
10552 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10553                                                  struct tevent_context *ev,
10554                                                  struct cli_state *cli,
10555                                                  const char *name)
10556 {
10557         struct tevent_req *req, *subreq;
10558         struct torture_createdel_state *state;
10559
10560         req = tevent_req_create(mem_ctx, &state,
10561                                 struct torture_createdel_state);
10562         if (req == NULL) {
10563                 return NULL;
10564         }
10565         state->ev = ev;
10566         state->cli = cli;
10567
10568         subreq = cli_ntcreate_send(
10569                 state, ev, cli, name, 0,
10570                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10571                 FILE_ATTRIBUTE_NORMAL,
10572                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10573                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10574                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10575
10576         if (tevent_req_nomem(subreq, req)) {
10577                 return tevent_req_post(req, ev);
10578         }
10579         tevent_req_set_callback(subreq, torture_createdel_created, req);
10580         return req;
10581 }
10582
10583 static void torture_createdel_created(struct tevent_req *subreq)
10584 {
10585         struct tevent_req *req = tevent_req_callback_data(
10586                 subreq, struct tevent_req);
10587         struct torture_createdel_state *state = tevent_req_data(
10588                 req, struct torture_createdel_state);
10589         NTSTATUS status;
10590         uint16_t fnum;
10591
10592         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10593         TALLOC_FREE(subreq);
10594         if (tevent_req_nterror(req, status)) {
10595                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10596                            nt_errstr(status)));
10597                 return;
10598         }
10599
10600         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10601         if (tevent_req_nomem(subreq, req)) {
10602                 return;
10603         }
10604         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10605 }
10606
10607 static void torture_createdel_closed(struct tevent_req *subreq)
10608 {
10609         struct tevent_req *req = tevent_req_callback_data(
10610                 subreq, struct tevent_req);
10611         NTSTATUS status;
10612
10613         status = cli_close_recv(subreq);
10614         if (tevent_req_nterror(req, status)) {
10615                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10616                 return;
10617         }
10618         tevent_req_done(req);
10619 }
10620
10621 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10622 {
10623         return tevent_req_simple_recv_ntstatus(req);
10624 }
10625
10626 struct torture_createdels_state {
10627         struct tevent_context *ev;
10628         struct cli_state *cli;
10629         const char *base_name;
10630         int sent;
10631         int received;
10632         int num_files;
10633         struct tevent_req **reqs;
10634 };
10635
10636 static void torture_createdels_done(struct tevent_req *subreq);
10637
10638 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10639                                                   struct tevent_context *ev,
10640                                                   struct cli_state *cli,
10641                                                   const char *base_name,
10642                                                   int num_parallel,
10643                                                   int num_files)
10644 {
10645         struct tevent_req *req;
10646         struct torture_createdels_state *state;
10647         int i;
10648
10649         req = tevent_req_create(mem_ctx, &state,
10650                                 struct torture_createdels_state);
10651         if (req == NULL) {
10652                 return NULL;
10653         }
10654         state->ev = ev;
10655         state->cli = cli;
10656         state->base_name = talloc_strdup(state, base_name);
10657         if (tevent_req_nomem(state->base_name, req)) {
10658                 return tevent_req_post(req, ev);
10659         }
10660         state->num_files = MAX(num_parallel, num_files);
10661         state->sent = 0;
10662         state->received = 0;
10663
10664         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10665         if (tevent_req_nomem(state->reqs, req)) {
10666                 return tevent_req_post(req, ev);
10667         }
10668
10669         for (i=0; i<num_parallel; i++) {
10670                 char *name;
10671
10672                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10673                                        state->sent);
10674                 if (tevent_req_nomem(name, req)) {
10675                         return tevent_req_post(req, ev);
10676                 }
10677                 state->reqs[i] = torture_createdel_send(
10678                         state->reqs, state->ev, state->cli, name);
10679                 if (tevent_req_nomem(state->reqs[i], req)) {
10680                         return tevent_req_post(req, ev);
10681                 }
10682                 name = talloc_move(state->reqs[i], &name);
10683                 tevent_req_set_callback(state->reqs[i],
10684                                         torture_createdels_done, req);
10685                 state->sent += 1;
10686         }
10687         return req;
10688 }
10689
10690 static void torture_createdels_done(struct tevent_req *subreq)
10691 {
10692         struct tevent_req *req = tevent_req_callback_data(
10693                 subreq, struct tevent_req);
10694         struct torture_createdels_state *state = tevent_req_data(
10695                 req, struct torture_createdels_state);
10696         size_t i, num_parallel = talloc_array_length(state->reqs);
10697         NTSTATUS status;
10698         char *name;
10699
10700         status = torture_createdel_recv(subreq);
10701         if (!NT_STATUS_IS_OK(status)){
10702                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10703                            nt_errstr(status)));
10704                 TALLOC_FREE(subreq);
10705                 tevent_req_nterror(req, status);
10706                 return;
10707         }
10708
10709         for (i=0; i<num_parallel; i++) {
10710                 if (subreq == state->reqs[i]) {
10711                         break;
10712                 }
10713         }
10714         if (i == num_parallel) {
10715                 DEBUG(10, ("received something we did not send\n"));
10716                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10717                 return;
10718         }
10719         TALLOC_FREE(state->reqs[i]);
10720
10721         if (state->sent >= state->num_files) {
10722                 tevent_req_done(req);
10723                 return;
10724         }
10725
10726         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10727                                state->sent);
10728         if (tevent_req_nomem(name, req)) {
10729                 return;
10730         }
10731         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10732                                                 state->cli, name);
10733         if (tevent_req_nomem(state->reqs[i], req)) {
10734                 return;
10735         }
10736         name = talloc_move(state->reqs[i], &name);
10737         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10738         state->sent += 1;
10739 }
10740
10741 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10742 {
10743         return tevent_req_simple_recv_ntstatus(req);
10744 }
10745
10746 struct swallow_notify_state {
10747         struct tevent_context *ev;
10748         struct cli_state *cli;
10749         uint16_t fnum;
10750         uint32_t completion_filter;
10751         bool recursive;
10752         bool (*fn)(uint32_t action, const char *name, void *priv);
10753         void *priv;
10754 };
10755
10756 static void swallow_notify_done(struct tevent_req *subreq);
10757
10758 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10759                                               struct tevent_context *ev,
10760                                               struct cli_state *cli,
10761                                               uint16_t fnum,
10762                                               uint32_t completion_filter,
10763                                               bool recursive,
10764                                               bool (*fn)(uint32_t action,
10765                                                          const char *name,
10766                                                          void *priv),
10767                                               void *priv)
10768 {
10769         struct tevent_req *req, *subreq;
10770         struct swallow_notify_state *state;
10771
10772         req = tevent_req_create(mem_ctx, &state,
10773                                 struct swallow_notify_state);
10774         if (req == NULL) {
10775                 return NULL;
10776         }
10777         state->ev = ev;
10778         state->cli = cli;
10779         state->fnum = fnum;
10780         state->completion_filter = completion_filter;
10781         state->recursive = recursive;
10782         state->fn = fn;
10783         state->priv = priv;
10784
10785         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10786                                  0xffff, state->completion_filter,
10787                                  state->recursive);
10788         if (tevent_req_nomem(subreq, req)) {
10789                 return tevent_req_post(req, ev);
10790         }
10791         tevent_req_set_callback(subreq, swallow_notify_done, req);
10792         return req;
10793 }
10794
10795 static void swallow_notify_done(struct tevent_req *subreq)
10796 {
10797         struct tevent_req *req = tevent_req_callback_data(
10798                 subreq, struct tevent_req);
10799         struct swallow_notify_state *state = tevent_req_data(
10800                 req, struct swallow_notify_state);
10801         NTSTATUS status;
10802         uint32_t i, num_changes;
10803         struct notify_change *changes;
10804
10805         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10806         TALLOC_FREE(subreq);
10807         if (!NT_STATUS_IS_OK(status)) {
10808                 DEBUG(10, ("cli_notify_recv returned %s\n",
10809                            nt_errstr(status)));
10810                 tevent_req_nterror(req, status);
10811                 return;
10812         }
10813
10814         for (i=0; i<num_changes; i++) {
10815                 state->fn(changes[i].action, changes[i].name, state->priv);
10816         }
10817         TALLOC_FREE(changes);
10818
10819         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10820                                  0xffff, state->completion_filter,
10821                                  state->recursive);
10822         if (tevent_req_nomem(subreq, req)) {
10823                 return;
10824         }
10825         tevent_req_set_callback(subreq, swallow_notify_done, req);
10826 }
10827
10828 static bool print_notifies(uint32_t action, const char *name, void *priv)
10829 {
10830         if (DEBUGLEVEL > 5) {
10831                 d_printf("%d %s\n", (int)action, name);
10832         }
10833         return true;
10834 }
10835
10836 static void notify_bench_done(struct tevent_req *req)
10837 {
10838         int *num_finished = (int *)tevent_req_callback_data_void(req);
10839         *num_finished += 1;
10840 }
10841
10842 static bool run_notify_bench(int dummy)
10843 {
10844         const char *dname = "\\notify-bench";
10845         struct tevent_context *ev;
10846         NTSTATUS status;
10847         uint16_t dnum;
10848         struct tevent_req *req1;
10849         struct tevent_req *req2 = NULL;
10850         int i, num_unc_names;
10851         int num_finished = 0;
10852
10853         printf("starting notify-bench test\n");
10854
10855         if (use_multishare_conn) {
10856                 char **unc_list;
10857                 unc_list = file_lines_load(multishare_conn_fname,
10858                                            &num_unc_names, 0, NULL);
10859                 if (!unc_list || num_unc_names <= 0) {
10860                         d_printf("Failed to load unc names list from '%s'\n",
10861                                  multishare_conn_fname);
10862                         return false;
10863                 }
10864                 TALLOC_FREE(unc_list);
10865         } else {
10866                 num_unc_names = 1;
10867         }
10868
10869         ev = samba_tevent_context_init(talloc_tos());
10870         if (ev == NULL) {
10871                 d_printf("tevent_context_init failed\n");
10872                 return false;
10873         }
10874
10875         for (i=0; i<num_unc_names; i++) {
10876                 struct cli_state *cli;
10877                 char *base_fname;
10878
10879                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10880                                              dname, i);
10881                 if (base_fname == NULL) {
10882                         return false;
10883                 }
10884
10885                 if (!torture_open_connection(&cli, i)) {
10886                         return false;
10887                 }
10888
10889                 status = cli_ntcreate(cli, dname, 0,
10890                                       MAXIMUM_ALLOWED_ACCESS,
10891                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10892                                       FILE_SHARE_DELETE,
10893                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10894                                       &dnum, NULL);
10895
10896                 if (!NT_STATUS_IS_OK(status)) {
10897                         d_printf("Could not create %s: %s\n", dname,
10898                                  nt_errstr(status));
10899                         return false;
10900                 }
10901
10902                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10903                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10904                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10905                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10906                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10907                                            false, print_notifies, NULL);
10908                 if (req1 == NULL) {
10909                         d_printf("Could not create notify request\n");
10910                         return false;
10911                 }
10912
10913                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10914                                                base_fname, 10, torture_numops);
10915                 if (req2 == NULL) {
10916                         d_printf("Could not create createdels request\n");
10917                         return false;
10918                 }
10919                 TALLOC_FREE(base_fname);
10920
10921                 tevent_req_set_callback(req2, notify_bench_done,
10922                                         &num_finished);
10923         }
10924
10925         while (num_finished < num_unc_names) {
10926                 int ret;
10927                 ret = tevent_loop_once(ev);
10928                 if (ret != 0) {
10929                         d_printf("tevent_loop_once failed\n");
10930                         return false;
10931                 }
10932         }
10933
10934         if (!tevent_req_poll(req2, ev)) {
10935                 d_printf("tevent_req_poll failed\n");
10936         }
10937
10938         status = torture_createdels_recv(req2);
10939         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10940
10941         return true;
10942 }
10943
10944 static bool run_mangle1(int dummy)
10945 {
10946         struct cli_state *cli;
10947         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10948         uint16_t fnum;
10949         fstring alt_name;
10950         NTSTATUS status;
10951         time_t change_time, access_time, write_time;
10952         off_t size;
10953         uint32_t attr;
10954
10955         printf("starting mangle1 test\n");
10956         if (!torture_open_connection(&cli, 0)) {
10957                 return False;
10958         }
10959
10960         smbXcli_conn_set_sockopt(cli->conn, sockops);
10961
10962         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10963                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10964                               0, 0, &fnum, NULL);
10965         if (!NT_STATUS_IS_OK(status)) {
10966                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10967                 return false;
10968         }
10969         cli_close(cli, fnum);
10970
10971         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10972         if (!NT_STATUS_IS_OK(status)) {
10973                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10974                          nt_errstr(status));
10975                 return false;
10976         }
10977         d_printf("alt_name: %s\n", alt_name);
10978
10979         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10980         if (!NT_STATUS_IS_OK(status)) {
10981                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10982                          nt_errstr(status));
10983                 return false;
10984         }
10985         cli_close(cli, fnum);
10986
10987         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10988                                 &write_time, &size, &attr);
10989         if (!NT_STATUS_IS_OK(status)) {
10990                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10991                          nt_errstr(status));
10992                 return false;
10993         }
10994
10995         return true;
10996 }
10997
10998 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
10999                                                  const char *mask,
11000                                                  void *state)
11001 {
11002         if (f->short_name == NULL) {
11003                 return NT_STATUS_OK;
11004         }
11005
11006         if (strlen(f->short_name) == 0) {
11007                 return NT_STATUS_OK;
11008         }
11009
11010         printf("unexpected shortname: %s\n", f->short_name);
11011
11012         return NT_STATUS_OBJECT_NAME_INVALID;
11013 }
11014
11015 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11016                                             const char *mask,
11017                                             void *state)
11018 {
11019         char *name = state;
11020
11021         printf("name: %s\n", f->name);
11022         fstrcpy(name, f->name);
11023         return NT_STATUS_OK;
11024 }
11025
11026 static bool run_mangle_illegal(int dummy)
11027 {
11028         struct cli_state *cli = NULL;
11029         struct cli_state *cli_posix = NULL;
11030         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11031         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11032         char *mangled_path = NULL;
11033         uint16_t fnum;
11034         fstring name;
11035         fstring alt_name;
11036         NTSTATUS status;
11037
11038         printf("starting mangle-illegal test\n");
11039
11040         if (!torture_open_connection(&cli, 0)) {
11041                 return False;
11042         }
11043
11044         smbXcli_conn_set_sockopt(cli->conn, sockops);
11045
11046         if (!torture_open_connection(&cli_posix, 0)) {
11047                 return false;
11048         }
11049
11050         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11051
11052         status = torture_setup_unix_extensions(cli_posix);
11053         if (!NT_STATUS_IS_OK(status)) {
11054                 return false;
11055         }
11056
11057         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11058         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11059         if (!NT_STATUS_IS_OK(status)) {
11060                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11061                 return False;
11062         }
11063
11064         /*
11065          * Create a file with illegal NTFS characters and test that we
11066          * get a usable mangled name
11067          */
11068
11069         cli_setatr(cli_posix, illegal_fname, 0, 0);
11070         cli_posix_unlink(cli_posix, illegal_fname);
11071
11072         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11073                                 0600, &fnum);
11074         if (!NT_STATUS_IS_OK(status)) {
11075                 printf("POSIX create of %s failed (%s)\n",
11076                        illegal_fname, nt_errstr(status));
11077                 return false;
11078         }
11079
11080         status = cli_close(cli_posix, fnum);
11081         if (!NT_STATUS_IS_OK(status)) {
11082                 printf("close failed (%s)\n", nt_errstr(status));
11083                 return false;
11084         }
11085
11086         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11087         if (!NT_STATUS_IS_OK(status)) {
11088                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11089                 return false;
11090         }
11091
11092         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11093         if (mangled_path == NULL) {
11094                 return false;
11095         }
11096
11097         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11098         if (!NT_STATUS_IS_OK(status)) {
11099                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11100                 TALLOC_FREE(mangled_path);
11101                 return false;
11102         }
11103         TALLOC_FREE(mangled_path);
11104         cli_close(cli, fnum);
11105
11106         cli_setatr(cli_posix, illegal_fname, 0, 0);
11107         cli_posix_unlink(cli_posix, illegal_fname);
11108
11109         /*
11110          * Create a file with a long name and check that we got *no* short name.
11111          */
11112
11113         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11114                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11115                               0, 0, &fnum, NULL);
11116         if (!NT_STATUS_IS_OK(status)) {
11117                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11118                 return false;
11119         }
11120         cli_close(cli, fnum);
11121
11122         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11123         if (!NT_STATUS_IS_OK(status)) {
11124                 d_printf("cli_list failed\n");
11125                 return false;
11126         }
11127
11128         cli_unlink(cli, fname, 0);
11129         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11130
11131         if (!torture_close_connection(cli_posix)) {
11132                 return false;
11133         }
11134
11135         if (!torture_close_connection(cli)) {
11136                 return false;
11137         }
11138
11139         return true;
11140 }
11141
11142 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11143 {
11144         size_t *to_pull = (size_t *)priv;
11145         size_t thistime = *to_pull;
11146
11147         thistime = MIN(thistime, n);
11148         if (thistime == 0) {
11149                 return 0;
11150         }
11151
11152         memset(buf, 0, thistime);
11153         *to_pull -= thistime;
11154         return thistime;
11155 }
11156
11157 static bool run_windows_write(int dummy)
11158 {
11159         struct cli_state *cli1;
11160         uint16_t fnum;
11161         int i;
11162         bool ret = false;
11163         const char *fname = "\\writetest.txt";
11164         struct timeval start_time;
11165         double seconds;
11166         double kbytes;
11167         NTSTATUS status;
11168
11169         printf("starting windows_write test\n");
11170         if (!torture_open_connection(&cli1, 0)) {
11171                 return False;
11172         }
11173
11174         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11175         if (!NT_STATUS_IS_OK(status)) {
11176                 printf("open failed (%s)\n", nt_errstr(status));
11177                 return False;
11178         }
11179
11180         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11181
11182         start_time = timeval_current();
11183
11184         for (i=0; i<torture_numops; i++) {
11185                 uint8_t c = 0;
11186                 off_t start = i * torture_blocksize;
11187                 size_t to_pull = torture_blocksize - 1;
11188
11189                 status = cli_writeall(cli1, fnum, 0, &c,
11190                                       start + torture_blocksize - 1, 1, NULL);
11191                 if (!NT_STATUS_IS_OK(status)) {
11192                         printf("cli_write failed: %s\n", nt_errstr(status));
11193                         goto fail;
11194                 }
11195
11196                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11197                                   null_source, &to_pull);
11198                 if (!NT_STATUS_IS_OK(status)) {
11199                         printf("cli_push returned: %s\n", nt_errstr(status));
11200                         goto fail;
11201                 }
11202         }
11203
11204         seconds = timeval_elapsed(&start_time);
11205         kbytes = (double)torture_blocksize * torture_numops;
11206         kbytes /= 1024;
11207
11208         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11209                (double)seconds, (int)(kbytes/seconds));
11210
11211         ret = true;
11212  fail:
11213         cli_close(cli1, fnum);
11214         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11215         torture_close_connection(cli1);
11216         return ret;
11217 }
11218
11219 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11220 {
11221         size_t max_pdu = 0x1FFFF;
11222
11223         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11224                 max_pdu = 0xFFFFFF;
11225         }
11226
11227         if (smb1cli_conn_signing_is_active(cli->conn)) {
11228                 max_pdu = 0x1FFFF;
11229         }
11230
11231         if (smb1cli_conn_encryption_on(cli->conn)) {
11232                 max_pdu = CLI_BUFFER_SIZE;
11233         }
11234
11235         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11236                 len_requested &= 0xFFFF;
11237         }
11238
11239         return MIN(len_requested,
11240                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11241 }
11242
11243 static bool check_read_call(struct cli_state *cli,
11244                             uint16_t fnum,
11245                             uint8_t *buf,
11246                             size_t len_requested)
11247 {
11248         NTSTATUS status;
11249         struct tevent_req *subreq = NULL;
11250         ssize_t len_read = 0;
11251         size_t len_expected = 0;
11252         struct tevent_context *ev = NULL;
11253
11254         ev = samba_tevent_context_init(talloc_tos());
11255         if (ev == NULL) {
11256                 return false;
11257         }
11258
11259         subreq = cli_read_andx_send(talloc_tos(),
11260                                     ev,
11261                                     cli,
11262                                     fnum,
11263                                     0,
11264                                     len_requested);
11265
11266         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11267                 return false;
11268         }
11269
11270         status = cli_read_andx_recv(subreq, &len_read, &buf);
11271         if (!NT_STATUS_IS_OK(status)) {
11272                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11273                 return false;
11274         }
11275
11276         TALLOC_FREE(subreq);
11277         TALLOC_FREE(ev);
11278
11279         len_expected = calc_expected_return(cli, len_requested);
11280
11281         if (len_expected > 0x10000 && len_read == 0x10000) {
11282                 /* Windows servers only return a max of 0x10000,
11283                    doesn't matter if you set CAP_LARGE_READX in
11284                    the client sessionsetupX call or not. */
11285                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11286                         (unsigned int)len_requested);
11287         } else if (len_read != len_expected) {
11288                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11289                         (unsigned int)len_requested,
11290                         (unsigned int)len_read,
11291                         (unsigned int)len_expected);
11292                 return false;
11293         } else {
11294                 d_printf("Correct read reply.\n");
11295         }
11296
11297         return true;
11298 }
11299
11300 /* Test large readX variants. */
11301 static bool large_readx_tests(struct cli_state *cli,
11302                                 uint16_t fnum,
11303                                 uint8_t *buf)
11304 {
11305         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11306         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11307                 return false;
11308         }
11309         /* A read of 0x10000 should return 0x10000 bytes. */
11310         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11311                 return false;
11312         }
11313         /* A read of 0x10000 should return 0x10001 bytes. */
11314         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11315                 return false;
11316         }
11317         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11318            the requested number of bytes. */
11319         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11320                 return false;
11321         }
11322         /* A read of 1MB should return 1MB bytes (on Samba). */
11323         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11324                 return false;
11325         }
11326
11327         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11328                 return false;
11329         }
11330         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11331                 return false;
11332         }
11333         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11334                 return false;
11335         }
11336         return true;
11337 }
11338
11339 static bool run_large_readx(int dummy)
11340 {
11341         uint8_t *buf = NULL;
11342         struct cli_state *cli1 = NULL;
11343         struct cli_state *cli2 = NULL;
11344         bool correct = false;
11345         const char *fname = "\\large_readx.dat";
11346         NTSTATUS status;
11347         uint16_t fnum1 = UINT16_MAX;
11348         uint32_t normal_caps = 0;
11349         size_t file_size = 20*1024*1024;
11350         TALLOC_CTX *frame = talloc_stackframe();
11351         size_t i;
11352         struct {
11353                 const char *name;
11354                 enum smb_signing_setting signing_setting;
11355                 enum protocol_types protocol;
11356         } runs[] = {
11357                 {
11358                         .name = "NT1",
11359                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11360                         .protocol = PROTOCOL_NT1,
11361                 },{
11362                         .name = "NT1 - SIGNING_REQUIRED",
11363                         .signing_setting = SMB_SIGNING_REQUIRED,
11364                         .protocol = PROTOCOL_NT1,
11365                 },
11366         };
11367
11368         printf("starting large_readx test\n");
11369
11370         if (!torture_open_connection(&cli1, 0)) {
11371                 goto out;
11372         }
11373
11374         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11375
11376         if (!(normal_caps & CAP_LARGE_READX)) {
11377                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11378                         (unsigned int)normal_caps);
11379                 goto out;
11380         }
11381
11382         /* Create a file of size 4MB. */
11383         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11384                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11385                         0, 0, &fnum1, NULL);
11386
11387         if (!NT_STATUS_IS_OK(status)) {
11388                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11389                 goto out;
11390         }
11391
11392         /* Write file_size bytes. */
11393         buf = talloc_zero_array(frame, uint8_t, file_size);
11394         if (buf == NULL) {
11395                 goto out;
11396         }
11397
11398         status = cli_writeall(cli1,
11399                               fnum1,
11400                               0,
11401                               buf,
11402                               0,
11403                               file_size,
11404                               NULL);
11405         if (!NT_STATUS_IS_OK(status)) {
11406                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11407                 goto out;
11408         }
11409
11410         status = cli_close(cli1, fnum1);
11411         if (!NT_STATUS_IS_OK(status)) {
11412                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11413                 goto out;
11414         }
11415
11416         fnum1 = UINT16_MAX;
11417
11418         for (i=0; i < ARRAY_SIZE(runs); i++) {
11419                 enum smb_signing_setting saved_signing_setting = signing_state;
11420                 uint16_t fnum2 = -1;
11421
11422                 if (do_encrypt &&
11423                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11424                 {
11425                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11426                         continue;
11427                 }
11428
11429                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11430
11431                 signing_state = runs[i].signing_setting;
11432                 cli2 = open_nbt_connection();
11433                 signing_state = saved_signing_setting;
11434                 if (cli2 == NULL) {
11435                         goto out;
11436                 }
11437
11438                 status = smbXcli_negprot(cli2->conn,
11439                                          cli2->timeout,
11440                                          runs[i].protocol,
11441                                          runs[i].protocol);
11442                 if (!NT_STATUS_IS_OK(status)) {
11443                         goto out;
11444                 }
11445
11446                 status = cli_session_setup_creds(cli2, torture_creds);
11447                 if (!NT_STATUS_IS_OK(status)) {
11448                         goto out;
11449                 }
11450
11451                 status = cli_tree_connect(cli2,
11452                                         share,
11453                                         "?????",
11454                                         password);
11455                 if (!NT_STATUS_IS_OK(status)) {
11456                         goto out;
11457                 }
11458
11459                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11460
11461                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11462
11463                 if (!(normal_caps & CAP_LARGE_READX)) {
11464                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11465                                 (unsigned int)normal_caps);
11466                         goto out;
11467                 }
11468
11469                 if (do_encrypt) {
11470                         if (force_cli_encryption(cli2, share) == false) {
11471                                 goto out;
11472                         }
11473                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11474                         uint16_t major, minor;
11475                         uint32_t caplow, caphigh;
11476
11477                         status = cli_unix_extensions_version(cli2,
11478                                                              &major, &minor,
11479                                                              &caplow, &caphigh);
11480                         if (!NT_STATUS_IS_OK(status)) {
11481                                 goto out;
11482                         }
11483                 }
11484
11485                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11486                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11487                                 0, 0, &fnum2, NULL);
11488                 if (!NT_STATUS_IS_OK(status)) {
11489                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11490                         goto out;
11491                 }
11492
11493                 /* All reads must return less than file_size bytes. */
11494                 if (!large_readx_tests(cli2, fnum2, buf)) {
11495                         goto out;
11496                 }
11497
11498                 status = cli_close(cli2, fnum2);
11499                 if (!NT_STATUS_IS_OK(status)) {
11500                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11501                         goto out;
11502                 }
11503                 fnum2 = -1;
11504
11505                 if (!torture_close_connection(cli2)) {
11506                         goto out;
11507                 }
11508                 cli2 = NULL;
11509         }
11510
11511         correct = true;
11512         printf("Success on large_readx test\n");
11513
11514   out:
11515
11516         if (cli2) {
11517                 if (!torture_close_connection(cli2)) {
11518                         correct = false;
11519                 }
11520         }
11521
11522         if (cli1) {
11523                 if (fnum1 != UINT16_MAX) {
11524                         status = cli_close(cli1, fnum1);
11525                         if (!NT_STATUS_IS_OK(status)) {
11526                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11527                         }
11528                         fnum1 = UINT16_MAX;
11529                 }
11530
11531                 status = cli_unlink(cli1, fname,
11532                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11533                 if (!NT_STATUS_IS_OK(status)) {
11534                         printf("unlink failed (%s)\n", nt_errstr(status));
11535                 }
11536
11537                 if (!torture_close_connection(cli1)) {
11538                         correct = false;
11539                 }
11540         }
11541
11542         TALLOC_FREE(frame);
11543
11544         printf("finished large_readx test\n");
11545         return correct;
11546 }
11547
11548 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11549                                   const char *mask,
11550                                   void *private_data)
11551 {
11552         uint32_t *p_attr = (uint32_t *)private_data;
11553
11554         if (strequal(finfo->name, test_filename)) {
11555                 *p_attr = finfo->attr;
11556         }
11557
11558         return NT_STATUS_OK;
11559 }
11560
11561 static bool run_msdfs_attribute(int dummy)
11562 {
11563         static struct cli_state *cli;
11564         bool correct = false;
11565         uint32_t attr = 0;
11566         NTSTATUS status;
11567
11568         printf("Starting MSDFS-ATTRIBUTE test\n");
11569
11570         if (test_filename == NULL || test_filename[0] == '\0') {
11571                 printf("MSDFS-ATTRIBUTE test "
11572                         "needs -f filename-of-msdfs-link\n");
11573                 return false;
11574         }
11575
11576         /*
11577          * NB. We use torture_open_connection_flags() not
11578          * torture_open_connection() as the latter forces
11579          * SMB1.
11580          */
11581         if (!torture_open_connection_flags(&cli, 0, 0)) {
11582                 return false;
11583         }
11584
11585         smbXcli_conn_set_sockopt(cli->conn, sockops);
11586
11587         status = cli_list(cli,
11588                         "*",
11589                         FILE_ATTRIBUTE_DIRECTORY,
11590                         msdfs_attribute_list_fn,
11591                         &attr);
11592
11593         if (!NT_STATUS_IS_OK(status)) {
11594                 printf("cli_list failed with %s\n",
11595                         nt_errstr(status));
11596                 goto out;
11597         }
11598         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11599                 printf("file %s should have "
11600                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11601                         test_filename,
11602                         (unsigned int)attr);
11603                 goto out;
11604         }
11605
11606         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11607                 printf("file %s should have "
11608                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11609                         test_filename,
11610                         (unsigned int)attr);
11611                 goto out;
11612         }
11613
11614         correct = true;
11615
11616   out:
11617
11618         torture_close_connection(cli);
11619         return correct;
11620 }
11621
11622 static bool run_cli_echo(int dummy)
11623 {
11624         struct cli_state *cli;
11625         NTSTATUS status;
11626
11627         printf("starting cli_echo test\n");
11628         if (!torture_open_connection(&cli, 0)) {
11629                 return false;
11630         }
11631         smbXcli_conn_set_sockopt(cli->conn, sockops);
11632
11633         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11634
11635         d_printf("cli_echo returned %s\n", nt_errstr(status));
11636
11637         torture_close_connection(cli);
11638         return NT_STATUS_IS_OK(status);
11639 }
11640
11641 static int splice_status(off_t written, void *priv)
11642 {
11643         return true;
11644 }
11645
11646 static bool run_cli_splice(int dummy)
11647 {
11648         uint8_t *buf = NULL;
11649         struct cli_state *cli1 = NULL;
11650         bool correct = false;
11651         const char *fname_src = "\\splice_src.dat";
11652         const char *fname_dst = "\\splice_dst.dat";
11653         NTSTATUS status;
11654         uint16_t fnum1 = UINT16_MAX;
11655         uint16_t fnum2 = UINT16_MAX;
11656         size_t file_size = 2*1024*1024;
11657         size_t splice_size = 1*1024*1024 + 713;
11658         uint8_t digest1[16], digest2[16];
11659         off_t written = 0;
11660         size_t nread = 0;
11661         TALLOC_CTX *frame = talloc_stackframe();
11662
11663         printf("starting cli_splice test\n");
11664
11665         if (!torture_open_connection(&cli1, 0)) {
11666                 goto out;
11667         }
11668
11669         cli_unlink(cli1, fname_src,
11670                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11671         cli_unlink(cli1, fname_dst,
11672                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11673
11674         /* Create a file */
11675         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11676                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11677                         0, 0, &fnum1, NULL);
11678
11679         if (!NT_STATUS_IS_OK(status)) {
11680                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11681                 goto out;
11682         }
11683
11684         /* Write file_size bytes - must be bigger than splice_size. */
11685         buf = talloc_zero_array(frame, uint8_t, file_size);
11686         if (buf == NULL) {
11687                 d_printf("talloc_fail\n");
11688                 goto out;
11689         }
11690
11691         /* Fill it with random numbers. */
11692         generate_random_buffer(buf, file_size);
11693
11694         /* MD5 the first 1MB + 713 bytes. */
11695         gnutls_hash_fast(GNUTLS_DIG_MD5,
11696                          buf,
11697                          splice_size,
11698                          digest1);
11699
11700         status = cli_writeall(cli1,
11701                               fnum1,
11702                               0,
11703                               buf,
11704                               0,
11705                               file_size,
11706                               NULL);
11707         if (!NT_STATUS_IS_OK(status)) {
11708                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11709                 goto out;
11710         }
11711
11712         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11713                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11714                         0, 0, &fnum2, NULL);
11715
11716         if (!NT_STATUS_IS_OK(status)) {
11717                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11718                 goto out;
11719         }
11720
11721         /* Now splice 1MB + 713 bytes. */
11722         status = cli_splice(cli1,
11723                                 cli1,
11724                                 fnum1,
11725                                 fnum2,
11726                                 splice_size,
11727                                 0,
11728                                 0,
11729                                 &written,
11730                                 splice_status,
11731                                 NULL);
11732
11733         if (!NT_STATUS_IS_OK(status)) {
11734                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11735                 goto out;
11736         }
11737
11738         /* Clear the old buffer. */
11739         memset(buf, '\0', file_size);
11740
11741         /* Read the new file. */
11742         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11743         if (!NT_STATUS_IS_OK(status)) {
11744                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11745                 goto out;
11746         }
11747         if (nread != splice_size) {
11748                 d_printf("bad read of 0x%x, should be 0x%x\n",
11749                         (unsigned int)nread,
11750                         (unsigned int)splice_size);
11751                 goto out;
11752         }
11753
11754         /* MD5 the first 1MB + 713 bytes. */
11755         gnutls_hash_fast(GNUTLS_DIG_MD5,
11756                          buf,
11757                          splice_size,
11758                          digest2);
11759
11760         /* Must be the same. */
11761         if (memcmp(digest1, digest2, 16) != 0) {
11762                 d_printf("bad MD5 compare\n");
11763                 goto out;
11764         }
11765
11766         correct = true;
11767         printf("Success on cli_splice test\n");
11768
11769   out:
11770
11771         if (cli1) {
11772                 if (fnum1 != UINT16_MAX) {
11773                         cli_close(cli1, fnum1);
11774                 }
11775                 if (fnum2 != UINT16_MAX) {
11776                         cli_close(cli1, fnum2);
11777                 }
11778
11779                 cli_unlink(cli1, fname_src,
11780                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11781                 cli_unlink(cli1, fname_dst,
11782                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11783
11784                 if (!torture_close_connection(cli1)) {
11785                         correct = false;
11786                 }
11787         }
11788
11789         TALLOC_FREE(frame);
11790         return correct;
11791 }
11792
11793 static bool run_uid_regression_test(int dummy)
11794 {
11795         static struct cli_state *cli;
11796         int16_t old_vuid;
11797         int32_t old_cnum;
11798         bool correct = True;
11799         struct smbXcli_tcon *tcon_copy = NULL;
11800         NTSTATUS status;
11801
11802         printf("starting uid regression test\n");
11803
11804         if (!torture_open_connection(&cli, 0)) {
11805                 return False;
11806         }
11807
11808         smbXcli_conn_set_sockopt(cli->conn, sockops);
11809
11810         /* Ok - now save then logoff our current user. */
11811         old_vuid = cli_state_get_uid(cli);
11812
11813         status = cli_ulogoff(cli);
11814         if (!NT_STATUS_IS_OK(status)) {
11815                 d_printf("(%s) cli_ulogoff failed: %s\n",
11816                          __location__, nt_errstr(status));
11817                 correct = false;
11818                 goto out;
11819         }
11820
11821         cli_state_set_uid(cli, old_vuid);
11822
11823         /* Try an operation. */
11824         status = cli_mkdir(cli, "\\uid_reg_test");
11825         if (NT_STATUS_IS_OK(status)) {
11826                 d_printf("(%s) cli_mkdir succeeded\n",
11827                          __location__);
11828                 correct = false;
11829                 goto out;
11830         } else {
11831                 /* Should be bad uid. */
11832                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11833                                  NT_STATUS_USER_SESSION_DELETED)) {
11834                         correct = false;
11835                         goto out;
11836                 }
11837         }
11838
11839         old_cnum = cli_state_get_tid(cli);
11840         /*
11841          * This is an SMB1-only test.
11842          * Copy the tcon, not "save/restore".
11843          *
11844          * In SMB1 the cli_tdis() below frees
11845          * cli->smb1.tcon so we need a copy
11846          * of the struct to put back for the
11847          * second tdis call with invalid vuid.
11848          *
11849          * This is a test-only hack. Real client code
11850          * uses cli_state_save_tcon()/cli_state_restore_tcon().
11851          */
11852         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11853         if (tcon_copy == NULL) {
11854                 correct = false;
11855                 goto out;
11856         }
11857
11858         /* Now try a SMBtdis with the invalid vuid set to zero. */
11859         cli_state_set_uid(cli, 0);
11860
11861         /* This should succeed. */
11862         status = cli_tdis(cli);
11863
11864         if (NT_STATUS_IS_OK(status)) {
11865                 d_printf("First tdis with invalid vuid should succeed.\n");
11866         } else {
11867                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11868                 correct = false;
11869                 cli->smb1.tcon = tcon_copy;
11870                 goto out;
11871         }
11872
11873         cli->smb1.tcon = tcon_copy;
11874         cli_state_set_uid(cli, old_vuid);
11875         cli_state_set_tid(cli, old_cnum);
11876
11877         /* This should fail. */
11878         status = cli_tdis(cli);
11879         if (NT_STATUS_IS_OK(status)) {
11880                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11881                 correct = false;
11882                 goto out;
11883         } else {
11884                 /* Should be bad tid. */
11885                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11886                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11887                         correct = false;
11888                         goto out;
11889                 }
11890         }
11891
11892         cli_rmdir(cli, "\\uid_reg_test");
11893
11894   out:
11895
11896         cli_shutdown(cli);
11897         return correct;
11898 }
11899
11900
11901 static const char *illegal_chars = "*\\/?<>|\":";
11902 static char force_shortname_chars[] = " +,.[];=\177";
11903
11904 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11905                              const char *mask, void *state)
11906 {
11907         struct cli_state *pcli = (struct cli_state *)state;
11908         fstring fname;
11909         NTSTATUS status = NT_STATUS_OK;
11910
11911         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11912
11913         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11914                 return NT_STATUS_OK;
11915
11916         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11917                 status = cli_rmdir(pcli, fname);
11918                 if (!NT_STATUS_IS_OK(status)) {
11919                         printf("del_fn: failed to rmdir %s\n,", fname );
11920                 }
11921         } else {
11922                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11923                 if (!NT_STATUS_IS_OK(status)) {
11924                         printf("del_fn: failed to unlink %s\n,", fname );
11925                 }
11926         }
11927         return status;
11928 }
11929
11930 struct sn_state {
11931         int matched;
11932         int i;
11933         bool val;
11934 };
11935
11936 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11937                               const char *name, void *state)
11938 {
11939         struct sn_state *s = (struct sn_state  *)state;
11940         int i = s->i;
11941
11942 #if 0
11943         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11944                 i, finfo->name, finfo->short_name);
11945 #endif
11946
11947         if (strchr(force_shortname_chars, i)) {
11948                 if (!finfo->short_name) {
11949                         /* Shortname not created when it should be. */
11950                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11951                                 __location__, finfo->name, i);
11952                         s->val = true;
11953                 }
11954         } else if (finfo->short_name){
11955                 /* Shortname created when it should not be. */
11956                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11957                         __location__, finfo->short_name, finfo->name);
11958                 s->val = true;
11959         }
11960         s->matched += 1;
11961         return NT_STATUS_OK;
11962 }
11963
11964 static bool run_shortname_test(int dummy)
11965 {
11966         static struct cli_state *cli;
11967         bool correct = True;
11968         int i;
11969         struct sn_state s;
11970         char fname[40];
11971         NTSTATUS status;
11972
11973         printf("starting shortname test\n");
11974
11975         if (!torture_open_connection(&cli, 0)) {
11976                 return False;
11977         }
11978
11979         smbXcli_conn_set_sockopt(cli->conn, sockops);
11980
11981         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11982         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11983         cli_rmdir(cli, "\\shortname");
11984
11985         status = cli_mkdir(cli, "\\shortname");
11986         if (!NT_STATUS_IS_OK(status)) {
11987                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11988                         __location__, nt_errstr(status));
11989                 correct = false;
11990                 goto out;
11991         }
11992
11993         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11994                 correct = false;
11995                 goto out;
11996         }
11997         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11998                 correct = false;
11999                 goto out;
12000         }
12001
12002         s.val = false;
12003
12004         for (i = 32; i < 128; i++) {
12005                 uint16_t fnum = (uint16_t)-1;
12006
12007                 s.i = i;
12008
12009                 if (strchr(illegal_chars, i)) {
12010                         continue;
12011                 }
12012                 fname[15] = i;
12013
12014                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12015                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12016                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12017                 if (!NT_STATUS_IS_OK(status)) {
12018                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12019                                 __location__, fname, nt_errstr(status));
12020                         correct = false;
12021                         goto out;
12022                 }
12023                 cli_close(cli, fnum);
12024
12025                 s.matched = 0;
12026                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12027                                   shortname_list_fn, &s);
12028                 if (s.matched != 1) {
12029                         d_printf("(%s) failed to list %s: %s\n",
12030                                 __location__, fname, nt_errstr(status));
12031                         correct = false;
12032                         goto out;
12033                 }
12034
12035                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12036                 if (!NT_STATUS_IS_OK(status)) {
12037                         d_printf("(%s) failed to delete %s: %s\n",
12038                                 __location__, fname, nt_errstr(status));
12039                         correct = false;
12040                         goto out;
12041                 }
12042
12043                 if (s.val) {
12044                         correct = false;
12045                         goto out;
12046                 }
12047         }
12048
12049   out:
12050
12051         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12052         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12053         cli_rmdir(cli, "\\shortname");
12054         torture_close_connection(cli);
12055         return correct;
12056 }
12057
12058 TLDAPRC callback_code;
12059
12060 static void pagedsearch_cb(struct tevent_req *req)
12061 {
12062         TLDAPRC rc;
12063         struct tldap_message *msg;
12064         char *dn;
12065
12066         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12067         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12068                 d_printf("tldap_search_paged_recv failed: %s\n",
12069                          tldap_rc2string(rc));
12070                 callback_code = rc;
12071                 return;
12072         }
12073         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12074                 TALLOC_FREE(msg);
12075                 return;
12076         }
12077         if (!tldap_entry_dn(msg, &dn)) {
12078                 d_printf("tldap_entry_dn failed\n");
12079                 return;
12080         }
12081         d_printf("%s\n", dn);
12082         TALLOC_FREE(msg);
12083 }
12084
12085 enum tldap_extended_val {
12086         EXTENDED_ZERO = 0,
12087         EXTENDED_ONE = 1,
12088         EXTENDED_NONE = 2,
12089 };
12090
12091 /*
12092  * Construct an extended dn control with either no value, 0 or 1
12093  *
12094  * No value and 0 are equivalent (non-hyphenated GUID)
12095  * 1 has the hyphenated GUID
12096  */
12097 static struct tldap_control *
12098 tldap_build_extended_control(enum tldap_extended_val val)
12099 {
12100         struct tldap_control empty_control;
12101         struct asn1_data *data;
12102
12103         ZERO_STRUCT(empty_control);
12104
12105         if (val != EXTENDED_NONE) {
12106                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12107
12108                 if (!data) {
12109                         return NULL;
12110                 }
12111
12112                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12113                         return NULL;
12114                 }
12115
12116                 if (!asn1_write_Integer(data, (int)val)) {
12117                         return NULL;
12118                 }
12119
12120                 if (!asn1_pop_tag(data)) {
12121                         return NULL;
12122                 }
12123
12124                 if (!asn1_blob(data, &empty_control.value)) {
12125                         return NULL;
12126                 }
12127         }
12128
12129         empty_control.oid = "1.2.840.113556.1.4.529";
12130         empty_control.critical = true;
12131
12132         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12133
12134 }
12135
12136 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12137                                       enum tldap_extended_val control_val)
12138 {
12139         struct tldap_control *control = tldap_build_extended_control(control_val);
12140         char *dn = NULL;
12141         struct tldap_message **msg;
12142         TLDAPRC rc;
12143
12144         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12145                           "(objectClass=*)", NULL, 0, 0,
12146                           control, 1, NULL,
12147                           0, 0, 0, 0, talloc_tos(), &msg);
12148         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12149                 d_printf("tldap_search for domain DN failed: %s\n",
12150                          tldap_errstr(talloc_tos(), ld, rc));
12151                 return false;
12152         }
12153
12154         if (!tldap_entry_dn(msg[0], &dn)) {
12155                 d_printf("tldap_search domain DN fetch failed: %s\n",
12156                          tldap_errstr(talloc_tos(), ld, rc));
12157                 return false;
12158         }
12159
12160         d_printf("%s\n", dn);
12161         {
12162                 uint32_t time_low;
12163                 uint32_t time_mid, time_hi_and_version;
12164                 uint32_t clock_seq[2];
12165                 uint32_t node[6];
12166                 char next;
12167
12168                 switch (control_val) {
12169                 case EXTENDED_NONE:
12170                 case EXTENDED_ZERO:
12171                         /*
12172                          * When reading GUIDs with hyphens, scanf will treat
12173                          * hyphen as a hex character (and counts as part of the
12174                          * width). This creates leftover GUID string which we
12175                          * check will for with 'next' and closing '>'.
12176                          */
12177                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12178                                          &time_low, &time_mid,
12179                                          &time_hi_and_version, &clock_seq[0],
12180                                          &clock_seq[1], &node[0], &node[1],
12181                                          &node[2], &node[3], &node[4],
12182                                          &node[5], &next)) {
12183                                 /* This GUID is good */
12184                         } else {
12185                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12186                                 return false;
12187                         }
12188
12189                         break;
12190                 case EXTENDED_ONE:
12191                         if (12 == sscanf(dn,
12192                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12193                                          &time_low, &time_mid,
12194                                          &time_hi_and_version, &clock_seq[0],
12195                                          &clock_seq[1], &node[0], &node[1],
12196                                          &node[2], &node[3], &node[4],
12197                                          &node[5], &next)) {
12198                                 /* This GUID is good */
12199                         } else {
12200                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12201                                 return false;
12202                         }
12203
12204                         break;
12205                 default:
12206                         return false;
12207                 }
12208         }
12209
12210         return true;
12211 }
12212
12213 static bool run_tldap(int dummy)
12214 {
12215         struct tldap_context *ld;
12216         int fd;
12217         TLDAPRC rc;
12218         NTSTATUS status;
12219         struct sockaddr_storage addr;
12220         struct tevent_context *ev;
12221         struct tevent_req *req;
12222         char *basedn;
12223         const char *filter;
12224
12225         if (!resolve_name(host, &addr, 0, false)) {
12226                 d_printf("could not find host %s\n", host);
12227                 return false;
12228         }
12229         status = open_socket_out(&addr, 389, 9999, &fd);
12230         if (!NT_STATUS_IS_OK(status)) {
12231                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12232                 return false;
12233         }
12234
12235         ld = tldap_context_create(talloc_tos(), fd);
12236         if (ld == NULL) {
12237                 close(fd);
12238                 d_printf("tldap_context_create failed\n");
12239                 return false;
12240         }
12241
12242         rc = tldap_fetch_rootdse(ld);
12243         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12244                 d_printf("tldap_fetch_rootdse failed: %s\n",
12245                          tldap_errstr(talloc_tos(), ld, rc));
12246                 return false;
12247         }
12248
12249         basedn = tldap_talloc_single_attribute(
12250                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12251         if (basedn == NULL) {
12252                 d_printf("no defaultNamingContext\n");
12253                 return false;
12254         }
12255         d_printf("defaultNamingContext: %s\n", basedn);
12256
12257         ev = samba_tevent_context_init(talloc_tos());
12258         if (ev == NULL) {
12259                 d_printf("tevent_context_init failed\n");
12260                 return false;
12261         }
12262
12263         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12264                                loadparm_init_s3(talloc_tos(),
12265                                                 loadparm_s3_helpers()),
12266                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12267
12268         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12269                 d_printf("tldap_gensec_bind failed\n");
12270                 return false;
12271         }
12272
12273         callback_code = TLDAP_SUCCESS;
12274
12275         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12276                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12277                                       NULL, 0, 0,
12278                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12279         if (req == NULL) {
12280                 d_printf("tldap_search_paged_send failed\n");
12281                 return false;
12282         }
12283         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12284
12285         tevent_req_poll(req, ev);
12286
12287         TALLOC_FREE(req);
12288
12289         rc = callback_code;
12290
12291         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12292                 d_printf("tldap_search with paging failed: %s\n",
12293                          tldap_errstr(talloc_tos(), ld, rc));
12294                 return false;
12295         }
12296
12297         /* test search filters against rootDSE */
12298         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12299                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12300
12301         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12302                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12303                           talloc_tos(), NULL);
12304         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12305                 d_printf("tldap_search with complex filter failed: %s\n",
12306                          tldap_errstr(talloc_tos(), ld, rc));
12307                 return false;
12308         }
12309
12310         /*
12311          * Tests to check for regression of:
12312          *
12313          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12314          *
12315          * TLDAP used here to pick apart the original string DN (with GUID)
12316          */
12317         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12318                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12319                          tldap_errstr(talloc_tos(), ld, rc));
12320                 return false;
12321         }
12322         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12323                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12324                          tldap_errstr(talloc_tos(), ld, rc));
12325                 return false;
12326         }
12327         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12328                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12329                          tldap_errstr(talloc_tos(), ld, rc));
12330                 return false;
12331         }
12332
12333         TALLOC_FREE(ld);
12334         return true;
12335 }
12336
12337 /* Torture test to ensure no regression of :
12338 https://bugzilla.samba.org/show_bug.cgi?id=7084
12339 */
12340
12341 static bool run_dir_createtime(int dummy)
12342 {
12343         struct cli_state *cli;
12344         const char *dname = "\\testdir_createtime";
12345         const char *fname = "\\testdir_createtime\\testfile";
12346         NTSTATUS status;
12347         struct timespec create_time;
12348         struct timespec create_time1;
12349         uint16_t fnum;
12350         bool ret = false;
12351         uint64_t ino;
12352
12353         if (!torture_open_connection(&cli, 0)) {
12354                 return false;
12355         }
12356
12357         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12358                 /* Ensure ino is zero, SMB2 gets a real one. */
12359                 ino = 0;
12360         } else {
12361                 /* Ensure ino is -1, SMB1 never gets a real one. */
12362                 ino = (uint64_t)-1;
12363         }
12364
12365         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12366         cli_rmdir(cli, dname);
12367
12368         status = cli_mkdir(cli, dname);
12369         if (!NT_STATUS_IS_OK(status)) {
12370                 printf("mkdir failed: %s\n", nt_errstr(status));
12371                 goto out;
12372         }
12373
12374         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12375                                 NULL, NULL, &ino);
12376         if (!NT_STATUS_IS_OK(status)) {
12377                 printf("cli_qpathinfo2 returned %s\n",
12378                        nt_errstr(status));
12379                 goto out;
12380         }
12381
12382         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12383                 /* SMB2 should always return an inode. */
12384                 if (ino == 0) {
12385                         printf("SMB2 bad inode (0)\n");
12386                         goto out;
12387                 }
12388         } else {
12389                 /* SMB1 must always return zero here. */
12390                 if (ino != 0) {
12391                         printf("SMB1 bad inode (!0)\n");
12392                         goto out;
12393                 }
12394         }
12395
12396         /* Sleep 3 seconds, then create a file. */
12397         sleep(3);
12398
12399         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12400                          DENY_NONE, &fnum);
12401         if (!NT_STATUS_IS_OK(status)) {
12402                 printf("cli_openx failed: %s\n", nt_errstr(status));
12403                 goto out;
12404         }
12405
12406         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12407                                 NULL, NULL, NULL);
12408         if (!NT_STATUS_IS_OK(status)) {
12409                 printf("cli_qpathinfo2 (2) returned %s\n",
12410                        nt_errstr(status));
12411                 goto out;
12412         }
12413
12414         if (timespec_compare(&create_time1, &create_time)) {
12415                 printf("run_dir_createtime: create time was updated (error)\n");
12416         } else {
12417                 printf("run_dir_createtime: create time was not updated (correct)\n");
12418                 ret = true;
12419         }
12420
12421   out:
12422
12423         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12424         cli_rmdir(cli, dname);
12425         if (!torture_close_connection(cli)) {
12426                 ret = false;
12427         }
12428         return ret;
12429 }
12430
12431
12432 static bool run_streamerror(int dummy)
12433 {
12434         struct cli_state *cli;
12435         const char *dname = "\\testdir_streamerror";
12436         const char *streamname =
12437                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12438         NTSTATUS status;
12439         time_t change_time, access_time, write_time;
12440         off_t size;
12441         uint16_t fnum;
12442         uint32_t attr;
12443         bool ret = true;
12444
12445         if (!torture_open_connection(&cli, 0)) {
12446                 return false;
12447         }
12448
12449         torture_deltree(cli, dname);
12450
12451         status = cli_mkdir(cli, dname);
12452         if (!NT_STATUS_IS_OK(status)) {
12453                 printf("mkdir failed: %s\n", nt_errstr(status));
12454                 return false;
12455         }
12456
12457         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12458                                 &write_time, &size, &attr);
12459         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12460                 printf("pathinfo returned %s, expected "
12461                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12462                        nt_errstr(status));
12463                 ret = false;
12464         }
12465
12466         status = cli_ntcreate(cli, streamname, 0x16,
12467                               FILE_READ_DATA|FILE_READ_EA|
12468                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12469                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12470                               FILE_OPEN, 0, 0, &fnum, NULL);
12471
12472         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12473                 printf("ntcreate returned %s, expected "
12474                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12475                        nt_errstr(status));
12476                 ret = false;
12477         }
12478
12479
12480         cli_rmdir(cli, dname);
12481         return ret;
12482 }
12483
12484 struct pidtest_state {
12485         bool success;
12486         uint16_t vwv[1];
12487         DATA_BLOB data;
12488 };
12489
12490 static void pid_echo_done(struct tevent_req *subreq);
12491
12492 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12493                         struct tevent_context *ev,
12494                         struct cli_state *cli)
12495 {
12496         struct tevent_req *req, *subreq;
12497         struct pidtest_state *state;
12498
12499         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12500         if (req == NULL) {
12501                 return NULL;
12502         }
12503
12504         SSVAL(state->vwv, 0, 1);
12505         state->data = data_blob_const("hello", 5);
12506
12507         subreq = smb1cli_req_send(state,
12508                                 ev,
12509                                 cli->conn,
12510                                 SMBecho,
12511                                 0, 0, /* *_flags */
12512                                 0, 0, /* *_flags2 */
12513                                 cli->timeout,
12514                                 0xDEADBEEF, /* pid */
12515                                 NULL, /* tcon */
12516                                 NULL, /* session */
12517                                 ARRAY_SIZE(state->vwv), state->vwv,
12518                                 state->data.length, state->data.data);
12519
12520         if (tevent_req_nomem(subreq, req)) {
12521                 return tevent_req_post(req, ev);
12522         }
12523         tevent_req_set_callback(subreq, pid_echo_done, req);
12524         return req;
12525 }
12526
12527 static void pid_echo_done(struct tevent_req *subreq)
12528 {
12529         struct tevent_req *req = tevent_req_callback_data(
12530                 subreq, struct tevent_req);
12531         struct pidtest_state *state = tevent_req_data(
12532                 req, struct pidtest_state);
12533         NTSTATUS status;
12534         uint32_t num_bytes;
12535         uint8_t *bytes = NULL;
12536         struct iovec *recv_iov = NULL;
12537         uint8_t *phdr = NULL;
12538         uint16_t pidlow = 0;
12539         uint16_t pidhigh = 0;
12540         struct smb1cli_req_expected_response expected[] = {
12541         {
12542                 .status = NT_STATUS_OK,
12543                 .wct    = 1,
12544         },
12545         };
12546
12547         status = smb1cli_req_recv(subreq, state,
12548                                 &recv_iov,
12549                                 &phdr,
12550                                 NULL, /* pwct */
12551                                 NULL, /* pvwv */
12552                                 NULL, /* pvwv_offset */
12553                                 &num_bytes,
12554                                 &bytes,
12555                                 NULL, /* pbytes_offset */
12556                                 NULL, /* pinbuf */
12557                                 expected, ARRAY_SIZE(expected));
12558
12559         TALLOC_FREE(subreq);
12560
12561         if (!NT_STATUS_IS_OK(status)) {
12562                 tevent_req_nterror(req, status);
12563                 return;
12564         }
12565
12566         if (num_bytes != state->data.length) {
12567                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12568                 return;
12569         }
12570
12571         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12572                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12573                 return;
12574         }
12575
12576         /* Check pid low/high == DEADBEEF */
12577         pidlow = SVAL(phdr, HDR_PID);
12578         if (pidlow != 0xBEEF){
12579                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12580                         (unsigned int)pidlow);
12581                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12582                 return;
12583         }
12584         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12585         if (pidhigh != 0xDEAD){
12586                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12587                         (unsigned int)pidhigh);
12588                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12589                 return;
12590         }
12591
12592         tevent_req_done(req);
12593 }
12594
12595 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12596 {
12597         return tevent_req_simple_recv_ntstatus(req);
12598 }
12599
12600 static bool run_pidhigh(int dummy)
12601 {
12602         bool success = false;
12603         struct cli_state *cli = NULL;
12604         NTSTATUS status;
12605         struct tevent_context *ev = NULL;
12606         struct tevent_req *req = NULL;
12607         TALLOC_CTX *frame = talloc_stackframe();
12608
12609         printf("starting pid high test\n");
12610         if (!torture_open_connection(&cli, 0)) {
12611                 return false;
12612         }
12613         smbXcli_conn_set_sockopt(cli->conn, sockops);
12614
12615         ev = samba_tevent_context_init(frame);
12616         if (ev == NULL) {
12617                 goto fail;
12618         }
12619
12620         req = pid_echo_send(frame, ev, cli);
12621         if (req == NULL) {
12622                 goto fail;
12623         }
12624
12625         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12626                 goto fail;
12627         }
12628
12629         status = pid_echo_recv(req);
12630         if (NT_STATUS_IS_OK(status)) {
12631                 printf("pid high test ok\n");
12632                 success = true;
12633         }
12634
12635  fail:
12636
12637         TALLOC_FREE(frame);
12638         torture_close_connection(cli);
12639         return success;
12640 }
12641
12642 /*
12643   Test Windows open on a bad POSIX symlink.
12644  */
12645 static bool run_symlink_open_test(int dummy)
12646 {
12647         static struct cli_state *cli;
12648         const char *fname = "non_existant_file";
12649         const char *sname = "dangling_symlink";
12650         uint16_t fnum = (uint16_t)-1;
12651         bool correct = false;
12652         NTSTATUS status;
12653         TALLOC_CTX *frame = NULL;
12654
12655         frame = talloc_stackframe();
12656
12657         printf("Starting Windows bad symlink open test\n");
12658
12659         if (!torture_open_connection(&cli, 0)) {
12660                 TALLOC_FREE(frame);
12661                 return false;
12662         }
12663
12664         smbXcli_conn_set_sockopt(cli->conn, sockops);
12665
12666         status = torture_setup_unix_extensions(cli);
12667         if (!NT_STATUS_IS_OK(status)) {
12668                 TALLOC_FREE(frame);
12669                 return false;
12670         }
12671
12672         /* Ensure nothing exists. */
12673         cli_setatr(cli, fname, 0, 0);
12674         cli_posix_unlink(cli, fname);
12675         cli_setatr(cli, sname, 0, 0);
12676         cli_posix_unlink(cli, sname);
12677
12678         /* Create a symlink pointing nowhere. */
12679         status = cli_posix_symlink(cli, fname, sname);
12680         if (!NT_STATUS_IS_OK(status)) {
12681                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12682                         sname,
12683                         fname,
12684                         nt_errstr(status));
12685                 goto out;
12686         }
12687
12688         /* Now ensure that a Windows open doesn't hang. */
12689         status = cli_ntcreate(cli,
12690                         sname,
12691                         0,
12692                         FILE_READ_DATA|FILE_WRITE_DATA,
12693                         0,
12694                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12695                         FILE_OPEN_IF,
12696                         0x0,
12697                         0x0,
12698                         &fnum,
12699                         NULL);
12700
12701         /*
12702          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12703          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12704          * we use O_NOFOLLOW on the server or not.
12705          */
12706         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12707             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12708         {
12709                 correct = true;
12710         } else {
12711                 printf("cli_ntcreate of %s returned %s - should return"
12712                                 " either (%s) or (%s)\n",
12713                         sname,
12714                         nt_errstr(status),
12715                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12716                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12717                 goto out;
12718         }
12719
12720         correct = true;
12721
12722   out:
12723
12724         if (fnum != (uint16_t)-1) {
12725                 cli_close(cli, fnum);
12726                 fnum = (uint16_t)-1;
12727         }
12728
12729         cli_setatr(cli, sname, 0, 0);
12730         cli_posix_unlink(cli, sname);
12731         cli_setatr(cli, fname, 0, 0);
12732         cli_posix_unlink(cli, fname);
12733
12734         if (!torture_close_connection(cli)) {
12735                 correct = false;
12736         }
12737
12738         TALLOC_FREE(frame);
12739         return correct;
12740 }
12741
12742 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12743                                         const char *name,
12744                                         void *state)
12745 {
12746         char **mangled_name_return = (char **)state;
12747         bool is_mangled = strchr(finfo->name, '~');
12748
12749         if (is_mangled) {
12750                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12751                 if (*mangled_name_return == NULL) {
12752                         return NT_STATUS_NO_MEMORY;
12753                 }
12754         }
12755         return NT_STATUS_OK;
12756 }
12757
12758 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12759 {
12760         static struct cli_state *cli_posix = NULL;
12761         static struct cli_state *cli = NULL;
12762         uint16_t fnum = (uint16_t)-1;
12763         bool correct = false;
12764         const char *dname = "smb1_wild_mangle_unlink";
12765         const char *aname = "smb1_wild_mangle_unlink/a";
12766         const char *star_name = "smb1_wild_mangle_unlink/*";
12767         char *windows_unlink_name = NULL;
12768         char *mangled_name = NULL;
12769         NTSTATUS status;
12770
12771         printf("Starting SMB1 wild mangle unlink test\n");
12772
12773         /* Open a Windows connection. */
12774         if (!torture_open_connection(&cli, 0)) {
12775                 return false;
12776         }
12777
12778         smbXcli_conn_set_sockopt(cli->conn, sockops);
12779
12780         /* Open a POSIX connection. */
12781         if (!torture_open_connection(&cli_posix, 0)) {
12782                 goto out;
12783         }
12784
12785         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12786
12787         status = torture_setup_unix_extensions(cli_posix);
12788         if (!NT_STATUS_IS_OK(status)) {
12789                 printf("server doesn't support POSIX\n");
12790                 goto out;
12791         }
12792
12793         /* Start fresh. */
12794         torture_deltree(cli, dname);
12795
12796         /*
12797          * Create two files - 'a' and '*'.
12798          * We need POSIX extensions for this as '*'
12799          * is not a valid Windows name.
12800          */
12801
12802         status = cli_mkdir(cli, dname);
12803         if (!NT_STATUS_IS_OK(status)) {
12804                 printf("cli_mkdir of %s returned %s\n",
12805                         dname,
12806                         nt_errstr(status));
12807                 goto out;
12808         }
12809
12810         status = cli_posix_open(cli_posix,
12811                                 aname,
12812                                 O_RDWR|O_CREAT|O_EXCL,
12813                                 0660,
12814                                 &fnum);
12815         if (!NT_STATUS_IS_OK(status)) {
12816                 printf("cli_posix_open (create) of %s returned %s\n",
12817                         aname,
12818                         nt_errstr(status));
12819                 goto out;
12820         }
12821         status = cli_close(cli_posix, fnum);
12822         if (!NT_STATUS_IS_OK(status)) {
12823                 goto out;
12824         }
12825         status = cli_posix_open(cli_posix,
12826                                 star_name,
12827                                 O_RDWR|O_CREAT|O_EXCL,
12828                                 0660,
12829                                 &fnum);
12830         if (!NT_STATUS_IS_OK(status)) {
12831                 printf("cli_posix_open (create) of %s returned %s\n",
12832                         star_name,
12833                         nt_errstr(status));
12834                 goto out;
12835         }
12836         status = cli_close(cli_posix, fnum);
12837         if (!NT_STATUS_IS_OK(status)) {
12838                 goto out;
12839         }
12840
12841         status = cli_list(cli,
12842                         star_name,
12843                         0,
12844                         smb1_wild_mangle_list_fn,
12845                         &mangled_name);
12846         if (!NT_STATUS_IS_OK(status)) {
12847                 printf("cli_list of %s returned %s\n",
12848                         star_name,
12849                         nt_errstr(status));
12850                 goto out;
12851         }
12852
12853         if (mangled_name == NULL) {
12854                 goto out;
12855         }
12856
12857         printf("mangled_name = %s\n",
12858                 mangled_name);
12859
12860         /*
12861          * Try a Windows unlink with the mangled name.
12862          * This should *NOT* unlink the 'a' name.
12863          */
12864
12865         windows_unlink_name = talloc_asprintf(cli_posix,
12866                                         "%s\\%s",
12867                                         dname,
12868                                         mangled_name);
12869
12870         status = cli_unlink(cli, windows_unlink_name, 0);
12871         if (!NT_STATUS_IS_OK(status)) {
12872                 printf("cli_unlink of %s returned %s\n",
12873                         windows_unlink_name,
12874                         nt_errstr(status));
12875                 goto out;
12876         }
12877
12878         /* Does 'a' still exist ? */
12879         status = cli_posix_open(cli_posix,
12880                                 aname,
12881                                 O_RDONLY,
12882                                 0,
12883                                 &fnum);
12884         if (!NT_STATUS_IS_OK(status)) {
12885                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12886                         aname,
12887                         nt_errstr(status));
12888                 goto out;
12889         }
12890
12891         status = cli_close(cli_posix, fnum);
12892         if (!NT_STATUS_IS_OK(status)) {
12893                 goto out;
12894         }
12895
12896         correct = true;
12897
12898   out:
12899
12900         TALLOC_FREE(windows_unlink_name);
12901         TALLOC_FREE(mangled_name);
12902
12903         if (cli != NULL) {
12904                 torture_deltree(cli, dname);
12905                 torture_close_connection(cli);
12906         }
12907
12908         if (cli_posix != NULL) {
12909                 torture_close_connection(cli_posix);
12910         }
12911
12912         return correct;
12913 }
12914
12915 static bool run_smb1_wild_mangle_rename_test(int dummy)
12916 {
12917         static struct cli_state *cli_posix = NULL;
12918         static struct cli_state *cli = NULL;
12919         uint16_t fnum = (uint16_t)-1;
12920         bool correct = false;
12921         const char *dname = "smb1_wild_mangle_rename";
12922         const char *fooname = "smb1_wild_mangle_rename/foo";
12923         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12924         const char *wild_name = "smb1_wild_mangle_rename/*";
12925         char *windows_rename_src = NULL;
12926         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12927         char *mangled_name = NULL;
12928         NTSTATUS status;
12929
12930         printf("Starting SMB1 wild mangle rename test\n");
12931
12932         if (!torture_open_connection(&cli_posix, 0)) {
12933                 return false;
12934         }
12935
12936         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12937
12938         status = torture_setup_unix_extensions(cli_posix);
12939         if (!NT_STATUS_IS_OK(status)) {
12940                 printf("server doesn't support POSIX\n");
12941                 return false;
12942         }
12943
12944         /* Open a Windows connection. */
12945         if (!torture_open_connection(&cli, 0)) {
12946                 goto out;
12947         }
12948
12949         smbXcli_conn_set_sockopt(cli->conn, sockops);
12950
12951         /* Ensure we start from fresh. */
12952         torture_deltree(cli, dname);
12953
12954         /*
12955          * Create two files - 'foo' and 'fo*'.
12956          * We need POSIX extensions for this as 'fo*'
12957          * is not a valid Windows name.
12958          */
12959
12960         status = cli_posix_mkdir(cli_posix, dname, 0770);
12961         if (!NT_STATUS_IS_OK(status)) {
12962                 printf("cli_posix_mkdir of %s returned %s\n",
12963                         dname,
12964                         nt_errstr(status));
12965                 goto out;
12966         }
12967
12968         status = cli_posix_open(cli_posix,
12969                                 fooname,
12970                                 O_RDWR|O_CREAT|O_EXCL,
12971                                 0660,
12972                                 &fnum);
12973         if (!NT_STATUS_IS_OK(status)) {
12974                 printf("cli_posix_open (create) of %s returned %s\n",
12975                         fooname,
12976                         nt_errstr(status));
12977                 goto out;
12978         }
12979         status = cli_close(cli_posix, fnum);
12980         if (!NT_STATUS_IS_OK(status)) {
12981                 goto out;
12982         }
12983         status = cli_posix_open(cli_posix,
12984                                 foostar_name,
12985                                 O_RDWR|O_CREAT|O_EXCL,
12986                                 0660,
12987                                 &fnum);
12988         if (!NT_STATUS_IS_OK(status)) {
12989                 printf("cli_posix_open (create) of %s returned %s\n",
12990                         foostar_name,
12991                         nt_errstr(status));
12992                 goto out;
12993         }
12994         status = cli_close(cli_posix, fnum);
12995         if (!NT_STATUS_IS_OK(status)) {
12996                 goto out;
12997         }
12998
12999         /*
13000          * Get the mangled name. We can re-use the
13001          * previous smb1_wild_mangle_list_fn for this.
13002          */
13003
13004         status = cli_list(cli,
13005                         wild_name,
13006                         0,
13007                         smb1_wild_mangle_list_fn,
13008                         &mangled_name);
13009         if (!NT_STATUS_IS_OK(status)) {
13010                 printf("cli_list of %s returned %s\n",
13011                         wild_name,
13012                         nt_errstr(status));
13013                 goto out;
13014         }
13015
13016         if (mangled_name == NULL) {
13017                 goto out;
13018         }
13019
13020         printf("mangled_name = %s\n",
13021                 mangled_name);
13022
13023         /*
13024          * Try a Windows rename with the mangled name.
13025          * This should *NOT* rename the 'foo' name.
13026          */
13027
13028         windows_rename_src = talloc_asprintf(cli_posix,
13029                                         "%s\\%s",
13030                                         dname,
13031                                         mangled_name);
13032
13033         status = cli_rename(cli,
13034                         windows_rename_src,
13035                         windows_rename_dst,
13036                         false);
13037         if (!NT_STATUS_IS_OK(status)) {
13038                 printf("cli_rename of %s -> %s returned %s\n",
13039                         windows_rename_src,
13040                         windows_rename_dst,
13041                         nt_errstr(status));
13042                 goto out;
13043         }
13044
13045         /* Does 'foo' still exist ? */
13046         status = cli_posix_open(cli_posix,
13047                                 fooname,
13048                                 O_RDONLY,
13049                                 0,
13050                                 &fnum);
13051         if (!NT_STATUS_IS_OK(status)) {
13052                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13053                         fooname,
13054                         nt_errstr(status));
13055                 goto out;
13056         }
13057
13058         status = cli_close(cli_posix, fnum);
13059         if (!NT_STATUS_IS_OK(status)) {
13060                 goto out;
13061         }
13062
13063         correct = true;
13064
13065   out:
13066
13067         TALLOC_FREE(mangled_name);
13068         TALLOC_FREE(windows_rename_src);
13069
13070         if (cli != NULL) {
13071                 torture_deltree(cli, dname);
13072                 torture_close_connection(cli);
13073         }
13074
13075         torture_close_connection(cli_posix);
13076
13077         return correct;
13078 }
13079
13080 /*
13081  * Only testing minimal time strings, as the others
13082  * need (locale-dependent) guessing at what strftime does and
13083  * even may differ in builds.
13084  */
13085 static bool timesubst_test(void)
13086 {
13087         TALLOC_CTX *ctx = NULL;
13088         /* Sa 23. Dez 04:33:20 CET 2017 */
13089         const struct timeval tv = { 1514000000, 123 };
13090         const char* expect_minimal = "20171223_033320";
13091         const char* expect_minus   = "20171223_033320_000123";
13092         char *s;
13093         char *env_tz, *orig_tz = NULL;
13094         bool result = true;
13095
13096         ctx = talloc_new(NULL);
13097
13098         env_tz = getenv("TZ");
13099         if(env_tz) {
13100                 orig_tz = talloc_strdup(ctx, env_tz);
13101         }
13102         setenv("TZ", "UTC", 1);
13103
13104         s = minimal_timeval_string(ctx, &tv, false);
13105
13106         if(!s || strcmp(s, expect_minimal)) {
13107                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13108                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13109                 result = false;
13110         }
13111         TALLOC_FREE(s);
13112         s = minimal_timeval_string(ctx, &tv, true);
13113         if(!s || strcmp(s, expect_minus)) {
13114                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13115                        "[%s]\n", s ? s : "<nil>", expect_minus);
13116                 result = false;
13117         }
13118         TALLOC_FREE(s);
13119
13120         if(orig_tz) {
13121                 setenv("TZ", orig_tz, 1);
13122         }
13123
13124         TALLOC_FREE(ctx);
13125         return result;
13126 }
13127
13128 static bool run_local_substitute(int dummy)
13129 {
13130         bool ok = true;
13131
13132         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13133         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13134         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13135         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13136         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13137         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13138         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13139         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13140         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13141         /* Substitution depends on current time, so better test the underlying
13142            formatting function. At least covers %t. */
13143         ok &= timesubst_test();
13144
13145         /* Different captialization rules in sub_basic... */
13146
13147         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13148                        "blaDOM") == 0);
13149
13150         return ok;
13151 }
13152
13153 static bool run_local_base64(int dummy)
13154 {
13155         int i;
13156         bool ret = true;
13157
13158         for (i=1; i<2000; i++) {
13159                 DATA_BLOB blob1, blob2;
13160                 char *b64;
13161
13162                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13163                 blob1.length = i;
13164                 generate_random_buffer(blob1.data, blob1.length);
13165
13166                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13167                 if (b64 == NULL) {
13168                         d_fprintf(stderr, "base64_encode_data_blob failed "
13169                                   "for %d bytes\n", i);
13170                         ret = false;
13171                 }
13172                 blob2 = base64_decode_data_blob(b64);
13173                 TALLOC_FREE(b64);
13174
13175                 if (data_blob_cmp(&blob1, &blob2)) {
13176                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13177                                   "bytes\n", i);
13178                         ret = false;
13179                 }
13180                 TALLOC_FREE(blob1.data);
13181                 data_blob_free(&blob2);
13182         }
13183         return ret;
13184 }
13185
13186 static void parse_fn(const struct gencache_timeout *t,
13187                      DATA_BLOB blob,
13188                      void *private_data)
13189 {
13190         return;
13191 }
13192
13193 static bool run_local_gencache(int dummy)
13194 {
13195         char *val;
13196         time_t tm;
13197         DATA_BLOB blob;
13198         char v;
13199         struct memcache *mem;
13200         int i;
13201
13202         mem = memcache_init(NULL, 0);
13203         if (mem == NULL) {
13204                 d_printf("%s: memcache_init failed\n", __location__);
13205                 return false;
13206         }
13207         memcache_set_global(mem);
13208
13209         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13210                 d_printf("%s: gencache_set() failed\n", __location__);
13211                 return False;
13212         }
13213
13214         if (!gencache_get("foo", NULL, NULL, NULL)) {
13215                 d_printf("%s: gencache_get() failed\n", __location__);
13216                 return False;
13217         }
13218
13219         for (i=0; i<1000000; i++) {
13220                 gencache_parse("foo", parse_fn, NULL);
13221         }
13222
13223         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13224                 d_printf("%s: gencache_get() failed\n", __location__);
13225                 return False;
13226         }
13227         TALLOC_FREE(val);
13228
13229         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13230                 d_printf("%s: gencache_get() failed\n", __location__);
13231                 return False;
13232         }
13233
13234         if (strcmp(val, "bar") != 0) {
13235                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13236                          __location__, val, "bar");
13237                 TALLOC_FREE(val);
13238                 return False;
13239         }
13240
13241         TALLOC_FREE(val);
13242
13243         if (!gencache_del("foo")) {
13244                 d_printf("%s: gencache_del() failed\n", __location__);
13245                 return False;
13246         }
13247         if (gencache_del("foo")) {
13248                 d_printf("%s: second gencache_del() succeeded\n",
13249                          __location__);
13250                 return False;
13251         }
13252
13253         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13254                 d_printf("%s: gencache_get() on deleted entry "
13255                          "succeeded\n", __location__);
13256                 return False;
13257         }
13258
13259         blob = data_blob_string_const_null("bar");
13260         tm = time(NULL) + 60;
13261
13262         if (!gencache_set_data_blob("foo", blob, tm)) {
13263                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13264                 return False;
13265         }
13266
13267         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13268                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13269                 return False;
13270         }
13271
13272         if (strcmp((const char *)blob.data, "bar") != 0) {
13273                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13274                          __location__, (const char *)blob.data, "bar");
13275                 data_blob_free(&blob);
13276                 return False;
13277         }
13278
13279         data_blob_free(&blob);
13280
13281         if (!gencache_del("foo")) {
13282                 d_printf("%s: gencache_del() failed\n", __location__);
13283                 return False;
13284         }
13285         if (gencache_del("foo")) {
13286                 d_printf("%s: second gencache_del() succeeded\n",
13287                          __location__);
13288                 return False;
13289         }
13290
13291         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13292                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13293                          "succeeded\n", __location__);
13294                 return False;
13295         }
13296
13297         v = 1;
13298         blob.data = (uint8_t *)&v;
13299         blob.length = sizeof(v);
13300
13301         if (!gencache_set_data_blob("blob", blob, tm)) {
13302                 d_printf("%s: gencache_set_data_blob() failed\n",
13303                          __location__);
13304                 return false;
13305         }
13306         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13307                 d_printf("%s: gencache_get succeeded\n", __location__);
13308                 return false;
13309         }
13310
13311         return True;
13312 }
13313
13314 static bool rbt_testflags(struct db_context *db, const char *key,
13315                           const char *value)
13316 {
13317         bool ret = false;
13318         NTSTATUS status;
13319         struct db_record *rec;
13320
13321         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13322         if (rec == NULL) {
13323                 d_fprintf(stderr, "fetch_locked failed\n");
13324                 goto done;
13325         }
13326
13327         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13328         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13329                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13330                           nt_errstr(status));
13331                 goto done;
13332         }
13333
13334         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13335                                      TDB_INSERT);
13336         if (!NT_STATUS_IS_OK(status)) {
13337                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13338                           nt_errstr(status));
13339                 goto done;
13340         }
13341
13342         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13343         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13344                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13345                           nt_errstr(status));
13346                 goto done;
13347         }
13348
13349         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13350         if (!NT_STATUS_IS_OK(status)) {
13351                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13352                           nt_errstr(status));
13353                 goto done;
13354         }
13355
13356         ret = true;
13357 done:
13358         TALLOC_FREE(rec);
13359         return ret;
13360 }
13361
13362 static bool rbt_testval(struct db_context *db, const char *key,
13363                         const char *value)
13364 {
13365         struct db_record *rec;
13366         TDB_DATA data = string_tdb_data(value);
13367         bool ret = false;
13368         NTSTATUS status;
13369         TDB_DATA dbvalue;
13370
13371         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13372         if (rec == NULL) {
13373                 d_fprintf(stderr, "fetch_locked failed\n");
13374                 goto done;
13375         }
13376         status = dbwrap_record_store(rec, data, 0);
13377         if (!NT_STATUS_IS_OK(status)) {
13378                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13379                 goto done;
13380         }
13381         TALLOC_FREE(rec);
13382
13383         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13384         if (rec == NULL) {
13385                 d_fprintf(stderr, "second fetch_locked failed\n");
13386                 goto done;
13387         }
13388
13389         dbvalue = dbwrap_record_get_value(rec);
13390         if ((dbvalue.dsize != data.dsize)
13391             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13392                 d_fprintf(stderr, "Got wrong data back\n");
13393                 goto done;
13394         }
13395
13396         ret = true;
13397  done:
13398         TALLOC_FREE(rec);
13399         return ret;
13400 }
13401
13402 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13403 {
13404         int *count2 = (int *)private_data;
13405         (*count2)++;
13406         return 0;
13407 }
13408
13409 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13410 {
13411         int *count2 = (int *)private_data;
13412         (*count2)++;
13413         dbwrap_record_delete(rec);
13414         return 0;
13415 }
13416
13417 static bool run_local_rbtree(int dummy)
13418 {
13419         struct db_context *db;
13420         bool ret = false;
13421         int i;
13422         NTSTATUS status;
13423         int count = 0;
13424         int count2 = 0;
13425
13426         db = db_open_rbt(NULL);
13427
13428         if (db == NULL) {
13429                 d_fprintf(stderr, "db_open_rbt failed\n");
13430                 return false;
13431         }
13432
13433         if (!rbt_testflags(db, "firstkey", "firstval")) {
13434                 goto done;
13435         }
13436
13437         for (i = 0; i < 999; i++) {
13438                 char key[sizeof("key-9223372036854775807")];
13439                 char value[sizeof("value-9223372036854775807")];
13440
13441                 snprintf(key, sizeof(key), "key%ld", random());
13442                 snprintf(value, sizeof(value) ,"value%ld", random());
13443
13444                 if (!rbt_testval(db, key, value)) {
13445                         goto done;
13446                 }
13447
13448                 snprintf(value, sizeof(value) ,"value%ld", random());
13449
13450                 if (!rbt_testval(db, key, value)) {
13451                         goto done;
13452                 }
13453         }
13454
13455         ret = true;
13456         count = 0; count2 = 0;
13457         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13458                                       &count2, &count);
13459         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13460         if ((count != count2) || (count != 1000)) {
13461                 ret = false;
13462         }
13463         count = 0; count2 = 0;
13464         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13465                                  &count2, &count);
13466         printf("%s: delete: %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_read(db, local_rbtree_traverse_read,
13472                                       &count2, &count);
13473         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13474         if ((count != count2) || (count != 0)) {
13475                 ret = false;
13476         }
13477
13478  done:
13479         TALLOC_FREE(db);
13480         return ret;
13481 }
13482
13483
13484 /*
13485   local test for character set functions
13486
13487   This is a very simple test for the functionality in convert_string_error()
13488  */
13489 static bool run_local_convert_string(int dummy)
13490 {
13491         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13492         const char *test_strings[2] = { "March", "M\303\244rz" };
13493         char dst[7];
13494         int i;
13495
13496         for (i=0; i<2; i++) {
13497                 const char *str = test_strings[i];
13498                 int len = strlen(str);
13499                 size_t converted_size;
13500                 bool ret;
13501
13502                 memset(dst, 'X', sizeof(dst));
13503
13504                 /* first try with real source length */
13505                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13506                                            str, len,
13507                                            dst, sizeof(dst),
13508                                            &converted_size);
13509                 if (ret != true) {
13510                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13511                         goto failed;
13512                 }
13513
13514                 if (converted_size != len) {
13515                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13516                                   str, len, (int)converted_size);
13517                         goto failed;
13518                 }
13519
13520                 if (strncmp(str, dst, converted_size) != 0) {
13521                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13522                         goto failed;
13523                 }
13524
13525                 if (strlen(str) != converted_size) {
13526                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13527                                   (int)strlen(str), (int)converted_size);
13528                         goto failed;
13529                 }
13530
13531                 if (dst[converted_size] != 'X') {
13532                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13533                         goto failed;
13534                 }
13535
13536                 /* now with srclen==-1, this causes the nul to be
13537                  * converted too */
13538                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13539                                            str, -1,
13540                                            dst, sizeof(dst),
13541                                            &converted_size);
13542                 if (ret != true) {
13543                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13544                         goto failed;
13545                 }
13546
13547                 if (converted_size != len+1) {
13548                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13549                                   str, len, (int)converted_size);
13550                         goto failed;
13551                 }
13552
13553                 if (strncmp(str, dst, converted_size) != 0) {
13554                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13555                         goto failed;
13556                 }
13557
13558                 if (len+1 != converted_size) {
13559                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13560                                   len+1, (int)converted_size);
13561                         goto failed;
13562                 }
13563
13564                 if (dst[converted_size] != 'X') {
13565                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13566                         goto failed;
13567                 }
13568
13569         }
13570
13571
13572         TALLOC_FREE(tmp_ctx);
13573         return true;
13574 failed:
13575         TALLOC_FREE(tmp_ctx);
13576         return false;
13577 }
13578
13579 static bool run_local_string_to_sid(int dummy) {
13580         struct dom_sid sid;
13581
13582         if (string_to_sid(&sid, "S--1-5-32-545")) {
13583                 printf("allowing S--1-5-32-545\n");
13584                 return false;
13585         }
13586         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13587                 printf("allowing S-1-5-32-+545\n");
13588                 return false;
13589         }
13590         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")) {
13591                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13592                 return false;
13593         }
13594         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13595                 printf("allowing S-1-5-32-545-abc\n");
13596                 return false;
13597         }
13598         if (string_to_sid(&sid, "S-300-5-32-545")) {
13599                 printf("allowing S-300-5-32-545\n");
13600                 return false;
13601         }
13602         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13603                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13604                 return false;
13605         }
13606         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13607                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13608                 return false;
13609         }
13610         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13611                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13612                 return false;
13613         }
13614         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13615                 printf("could not parse S-1-5-32-545\n");
13616                 return false;
13617         }
13618         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13619                 struct dom_sid_buf buf;
13620                 printf("mis-parsed S-1-5-32-545 as %s\n",
13621                        dom_sid_str_buf(&sid, &buf));
13622                 return false;
13623         }
13624         return true;
13625 }
13626
13627 static bool sid_to_string_test(const char *expected) {
13628         char *str;
13629         bool res = true;
13630         struct dom_sid sid;
13631
13632         if (!string_to_sid(&sid, expected)) {
13633                 printf("could not parse %s\n", expected);
13634                 return false;
13635         }
13636
13637         str = dom_sid_string(NULL, &sid);
13638         if (strcmp(str, expected)) {
13639                 printf("Comparison failed (%s != %s)\n", str, expected);
13640                 res = false;
13641         }
13642         TALLOC_FREE(str);
13643         return res;
13644 }
13645
13646 static bool run_local_sid_to_string(int dummy) {
13647         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13648                 return false;
13649         if (!sid_to_string_test("S-1-545"))
13650                 return false;
13651         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13652                 return false;
13653         return true;
13654 }
13655
13656 static bool run_local_binary_to_sid(int dummy) {
13657         ssize_t ret;
13658         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13659         static const uint8_t good_binary_sid[] = {
13660                 0x1, /* revision number */
13661                 15, /* num auths */
13662                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13663                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13664                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13665                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13666                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13667                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13668                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13669                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13670                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13671                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13672                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13673                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13674                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13675                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13676                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13677                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13678         };
13679
13680         static const uint8_t long_binary_sid[] = {
13681                 0x1, /* revision number */
13682                 15, /* num auths */
13683                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13684                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13685                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13686                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13687                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13688                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13689                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13690                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13691                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13692                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13693                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13694                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13695                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13696                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13697                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13698                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13699                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13700                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13701                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13702         };
13703
13704         static const uint8_t long_binary_sid2[] = {
13705                 0x1, /* revision number */
13706                 32, /* num auths */
13707                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13708                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13709                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13710                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13711                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13712                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13713                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13714                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13715                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13716                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13717                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13718                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13719                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13720                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13721                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13722                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13723                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13724                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13725                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13726                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13727                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13728                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13729                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13730                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13731                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13732                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13733                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13734                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13735                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13736                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13737                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13738                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13739                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13740         };
13741
13742         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13743         if (ret == -1) {
13744                 return false;
13745         }
13746         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13747         if (ret != -1) {
13748                 return false;
13749         }
13750         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13751         if (ret != -1) {
13752                 return false;
13753         }
13754         return true;
13755 }
13756
13757 /* Split a path name into filename and stream name components. Canonicalise
13758  * such that an implicit $DATA token is always explicit.
13759  *
13760  * The "specification" of this function can be found in the
13761  * run_local_stream_name() function in torture.c, I've tried those
13762  * combinations against a W2k3 server.
13763  */
13764
13765 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13766                                        char **pbase, char **pstream)
13767 {
13768         char *base = NULL;
13769         char *stream = NULL;
13770         char *sname; /* stream name */
13771         const char *stype; /* stream type */
13772
13773         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13774
13775         sname = strchr_m(fname, ':');
13776
13777         if (sname == NULL) {
13778                 if (pbase != NULL) {
13779                         base = talloc_strdup(mem_ctx, fname);
13780                         NT_STATUS_HAVE_NO_MEMORY(base);
13781                 }
13782                 goto done;
13783         }
13784
13785         if (pbase != NULL) {
13786                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13787                 NT_STATUS_HAVE_NO_MEMORY(base);
13788         }
13789
13790         sname += 1;
13791
13792         stype = strchr_m(sname, ':');
13793
13794         if (stype == NULL) {
13795                 sname = talloc_strdup(mem_ctx, sname);
13796                 stype = "$DATA";
13797         }
13798         else {
13799                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13800                         /*
13801                          * If there is an explicit stream type, so far we only
13802                          * allow $DATA. Is there anything else allowed? -- vl
13803                          */
13804                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13805                         TALLOC_FREE(base);
13806                         return NT_STATUS_OBJECT_NAME_INVALID;
13807                 }
13808                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13809                 stype += 1;
13810         }
13811
13812         if (sname == NULL) {
13813                 TALLOC_FREE(base);
13814                 return NT_STATUS_NO_MEMORY;
13815         }
13816
13817         if (sname[0] == '\0') {
13818                 /*
13819                  * no stream name, so no stream
13820                  */
13821                 goto done;
13822         }
13823
13824         if (pstream != NULL) {
13825                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13826                 if (stream == NULL) {
13827                         TALLOC_FREE(sname);
13828                         TALLOC_FREE(base);
13829                         return NT_STATUS_NO_MEMORY;
13830                 }
13831                 /*
13832                  * upper-case the type field
13833                  */
13834                 (void)strupper_m(strchr_m(stream, ':')+1);
13835         }
13836
13837  done:
13838         if (pbase != NULL) {
13839                 *pbase = base;
13840         }
13841         if (pstream != NULL) {
13842                 *pstream = stream;
13843         }
13844         return NT_STATUS_OK;
13845 }
13846
13847 static bool test_stream_name(const char *fname, const char *expected_base,
13848                              const char *expected_stream,
13849                              NTSTATUS expected_status)
13850 {
13851         NTSTATUS status;
13852         char *base = NULL;
13853         char *stream = NULL;
13854
13855         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13856         if (!NT_STATUS_EQUAL(status, expected_status)) {
13857                 goto error;
13858         }
13859
13860         if (!NT_STATUS_IS_OK(status)) {
13861                 return true;
13862         }
13863
13864         if (base == NULL) goto error;
13865
13866         if (strcmp(expected_base, base) != 0) goto error;
13867
13868         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13869         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13870
13871         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13872                 goto error;
13873
13874         TALLOC_FREE(base);
13875         TALLOC_FREE(stream);
13876         return true;
13877
13878  error:
13879         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13880                   fname, expected_base ? expected_base : "<NULL>",
13881                   expected_stream ? expected_stream : "<NULL>",
13882                   nt_errstr(expected_status));
13883         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13884                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13885                   nt_errstr(status));
13886         TALLOC_FREE(base);
13887         TALLOC_FREE(stream);
13888         return false;
13889 }
13890
13891 static bool run_local_stream_name(int dummy)
13892 {
13893         bool ret = true;
13894
13895         ret &= test_stream_name(
13896                 "bla", "bla", NULL, NT_STATUS_OK);
13897         ret &= test_stream_name(
13898                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13899         ret &= test_stream_name(
13900                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13901         ret &= test_stream_name(
13902                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13903         ret &= test_stream_name(
13904                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13905         ret &= test_stream_name(
13906                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13907         ret &= test_stream_name(
13908                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13909         ret &= test_stream_name(
13910                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13911
13912         return ret;
13913 }
13914
13915 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13916 {
13917         if (a.length != b.length) {
13918                 printf("a.length=%d != b.length=%d\n",
13919                        (int)a.length, (int)b.length);
13920                 return false;
13921         }
13922         if (memcmp(a.data, b.data, a.length) != 0) {
13923                 printf("a.data and b.data differ\n");
13924                 return false;
13925         }
13926         return true;
13927 }
13928
13929 static bool run_local_memcache(int dummy)
13930 {
13931         struct memcache *cache;
13932         DATA_BLOB k1, k2, k3, k4, k5;
13933         DATA_BLOB d1, d3;
13934         DATA_BLOB v1, v3;
13935
13936         TALLOC_CTX *mem_ctx;
13937         char *ptr1 = NULL;
13938         char *ptr2 = NULL;
13939         char *ptr3 = NULL;
13940
13941         char *str1, *str2;
13942         size_t size1, size2;
13943         bool ret = false;
13944
13945         mem_ctx = talloc_init("foo");
13946         if (mem_ctx == NULL) {
13947                 return false;
13948         }
13949
13950         /* STAT_CACHE TESTS */
13951
13952         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13953
13954         if (cache == NULL) {
13955                 printf("memcache_init failed\n");
13956                 return false;
13957         }
13958
13959         d1 = data_blob_const("d1", 2);
13960         d3 = data_blob_const("d3", 2);
13961
13962         k1 = data_blob_const("d1", 2);
13963         k2 = data_blob_const("d2", 2);
13964         k3 = data_blob_const("d3", 2);
13965         k4 = data_blob_const("d4", 2);
13966         k5 = data_blob_const("d5", 2);
13967
13968         memcache_add(cache, STAT_CACHE, k1, d1);
13969
13970         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13971                 printf("could not find k1\n");
13972                 return false;
13973         }
13974         if (!data_blob_equal(d1, v1)) {
13975                 return false;
13976         }
13977
13978         memcache_add(cache, STAT_CACHE, k1, d3);
13979
13980         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13981                 printf("could not find replaced k1\n");
13982                 return false;
13983         }
13984         if (!data_blob_equal(d3, v3)) {
13985                 return false;
13986         }
13987
13988         TALLOC_FREE(cache);
13989
13990         /* GETWD_CACHE TESTS */
13991         str1 = talloc_strdup(mem_ctx, "string1");
13992         if (str1 == NULL) {
13993                 return false;
13994         }
13995         ptr2 = str1; /* Keep an alias for comparison. */
13996
13997         str2 = talloc_strdup(mem_ctx, "string2");
13998         if (str2 == NULL) {
13999                 return false;
14000         }
14001
14002         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14003         if (cache == NULL) {
14004                 printf("memcache_init failed\n");
14005                 return false;
14006         }
14007
14008         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14009         /* str1 == NULL now. */
14010         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14011         if (ptr1 == NULL) {
14012                 printf("could not find k2\n");
14013                 return false;
14014         }
14015         if (ptr1 != ptr2) {
14016                 printf("fetch of k2 got wrong string\n");
14017                 return false;
14018         }
14019
14020         /* Add a blob to ensure k2 gets purged. */
14021         d3 = data_blob_talloc_zero(mem_ctx, 180);
14022         memcache_add(cache, STAT_CACHE, k3, d3);
14023
14024         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14025         if (ptr2 != NULL) {
14026                 printf("Did find k2, should have been purged\n");
14027                 return false;
14028         }
14029
14030         /*
14031          * Test that talloc size also is accounted in memcache and
14032          * causes purge of other object.
14033          */
14034
14035         str1 = talloc_zero_size(mem_ctx, 100);
14036         str2 = talloc_zero_size(mem_ctx, 100);
14037
14038         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14039         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14040
14041         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14042         if (ptr3 != NULL) {
14043                 printf("Did find k4, should have been purged\n");
14044                 return false;
14045         }
14046
14047         /*
14048          * Test that adding a duplicate non-talloced
14049          * key/value on top of a talloced key/value takes account
14050          * of the talloc_freed value size.
14051          */
14052         TALLOC_FREE(cache);
14053         TALLOC_FREE(mem_ctx);
14054
14055         mem_ctx = talloc_init("key_replace");
14056         if (mem_ctx == NULL) {
14057                 return false;
14058         }
14059
14060         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14061         if (cache == NULL) {
14062                 return false;
14063         }
14064
14065         /*
14066          * Add a 100 byte talloced string. This will
14067          * store a (4 or 8 byte) pointer and record the
14068          * total talloced size.
14069          */
14070         str1 = talloc_zero_size(mem_ctx, 100);
14071         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14072         /*
14073          * Now overwrite with a small talloced
14074          * value. This should fit in the existing size
14075          * and the total talloced size should be removed
14076          * from the cache size.
14077          */
14078         str1 = talloc_zero_size(mem_ctx, 2);
14079         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14080         /*
14081          * Now store a 20 byte string. If the
14082          * total talloced size wasn't accounted for
14083          * and removed in the overwrite, then this
14084          * will evict k4.
14085          */
14086         str2 = talloc_zero_size(mem_ctx, 20);
14087         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14088
14089         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14090         if (ptr3 == NULL) {
14091                 printf("Did not find k4, should not have been purged\n");
14092                 return false;
14093         }
14094
14095         TALLOC_FREE(cache);
14096         TALLOC_FREE(mem_ctx);
14097
14098         mem_ctx = talloc_init("foo");
14099         if (mem_ctx == NULL) {
14100                 return false;
14101         }
14102
14103         cache = memcache_init(NULL, 0);
14104         if (cache == NULL) {
14105                 return false;
14106         }
14107
14108         str1 = talloc_strdup(mem_ctx, "string1");
14109         if (str1 == NULL) {
14110                 return false;
14111         }
14112         str2 = talloc_strdup(mem_ctx, "string2");
14113         if (str2 == NULL) {
14114                 return false;
14115         }
14116         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14117                             data_blob_string_const("torture"), &str1);
14118         size1 = talloc_total_size(cache);
14119
14120         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14121                             data_blob_string_const("torture"), &str2);
14122         size2 = talloc_total_size(cache);
14123
14124         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14125
14126         if (size2 > size1) {
14127                 printf("memcache leaks memory!\n");
14128                 goto fail;
14129         }
14130
14131         ret = true;
14132  fail:
14133         TALLOC_FREE(cache);
14134         return ret;
14135 }
14136
14137 static void wbclient_done(struct tevent_req *req)
14138 {
14139         wbcErr wbc_err;
14140         struct winbindd_response *wb_resp;
14141         int *i = (int *)tevent_req_callback_data_void(req);
14142
14143         wbc_err = wb_trans_recv(req, req, &wb_resp);
14144         TALLOC_FREE(req);
14145         *i += 1;
14146         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14147 }
14148
14149 static bool run_wbclient_multi_ping(int dummy)
14150 {
14151         struct tevent_context *ev;
14152         struct wb_context **wb_ctx;
14153         struct winbindd_request wb_req;
14154         bool result = false;
14155         int i, j;
14156
14157         BlockSignals(True, SIGPIPE);
14158
14159         ev = tevent_context_init(talloc_tos());
14160         if (ev == NULL) {
14161                 goto fail;
14162         }
14163
14164         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14165         if (wb_ctx == NULL) {
14166                 goto fail;
14167         }
14168
14169         ZERO_STRUCT(wb_req);
14170         wb_req.cmd = WINBINDD_PING;
14171
14172         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14173
14174         for (i=0; i<torture_nprocs; i++) {
14175                 wb_ctx[i] = wb_context_init(ev, NULL);
14176                 if (wb_ctx[i] == NULL) {
14177                         goto fail;
14178                 }
14179                 for (j=0; j<torture_numops; j++) {
14180                         struct tevent_req *req;
14181                         req = wb_trans_send(ev, ev, wb_ctx[i],
14182                                             (j % 2) == 0, &wb_req);
14183                         if (req == NULL) {
14184                                 goto fail;
14185                         }
14186                         tevent_req_set_callback(req, wbclient_done, &i);
14187                 }
14188         }
14189
14190         i = 0;
14191
14192         while (i < torture_nprocs * torture_numops) {
14193                 tevent_loop_once(ev);
14194         }
14195
14196         result = true;
14197  fail:
14198         TALLOC_FREE(ev);
14199         return result;
14200 }
14201
14202 static bool dbtrans_inc(struct db_context *db)
14203 {
14204         struct db_record *rec;
14205         uint32_t val;
14206         bool ret = false;
14207         NTSTATUS status;
14208         TDB_DATA value;
14209
14210         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14211         if (rec == NULL) {
14212                 printf(__location__ "fetch_lock failed\n");
14213                 return false;
14214         }
14215
14216         value = dbwrap_record_get_value(rec);
14217
14218         if (value.dsize != sizeof(uint32_t)) {
14219                 printf(__location__ "value.dsize = %d\n",
14220                        (int)value.dsize);
14221                 goto fail;
14222         }
14223
14224         memcpy(&val, value.dptr, sizeof(val));
14225         val += 1;
14226
14227         status = dbwrap_record_store(
14228                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14229         if (!NT_STATUS_IS_OK(status)) {
14230                 printf(__location__ "store failed: %s\n",
14231                        nt_errstr(status));
14232                 goto fail;
14233         }
14234
14235         ret = true;
14236 fail:
14237         TALLOC_FREE(rec);
14238         return ret;
14239 }
14240
14241 static bool run_local_dbtrans(int dummy)
14242 {
14243         struct db_context *db;
14244         struct db_record *rec;
14245         NTSTATUS status;
14246         uint32_t initial;
14247         int res;
14248         TDB_DATA value;
14249
14250         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14251                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14252                      DBWRAP_FLAG_NONE);
14253         if (db == NULL) {
14254                 printf("Could not open transtest.db\n");
14255                 return false;
14256         }
14257
14258         res = dbwrap_transaction_start(db);
14259         if (res != 0) {
14260                 printf(__location__ "transaction_start failed\n");
14261                 return false;
14262         }
14263
14264         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14265         if (rec == NULL) {
14266                 printf(__location__ "fetch_lock failed\n");
14267                 return false;
14268         }
14269
14270         value = dbwrap_record_get_value(rec);
14271
14272         if (value.dptr == NULL) {
14273                 initial = 0;
14274                 status = dbwrap_record_store(
14275                         rec, make_tdb_data((uint8_t *)&initial,
14276                                            sizeof(initial)),
14277                         0);
14278                 if (!NT_STATUS_IS_OK(status)) {
14279                         printf(__location__ "store returned %s\n",
14280                                nt_errstr(status));
14281                         return false;
14282                 }
14283         }
14284
14285         TALLOC_FREE(rec);
14286
14287         res = dbwrap_transaction_commit(db);
14288         if (res != 0) {
14289                 printf(__location__ "transaction_commit failed\n");
14290                 return false;
14291         }
14292
14293         while (true) {
14294                 uint32_t val, val2;
14295                 int i;
14296
14297                 res = dbwrap_transaction_start(db);
14298                 if (res != 0) {
14299                         printf(__location__ "transaction_start failed\n");
14300                         break;
14301                 }
14302
14303                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14304                 if (!NT_STATUS_IS_OK(status)) {
14305                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14306                                nt_errstr(status));
14307                         break;
14308                 }
14309
14310                 for (i=0; i<10; i++) {
14311                         if (!dbtrans_inc(db)) {
14312                                 return false;
14313                         }
14314                 }
14315
14316                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14317                 if (!NT_STATUS_IS_OK(status)) {
14318                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14319                                nt_errstr(status));
14320                         break;
14321                 }
14322
14323                 if (val2 != val + 10) {
14324                         printf(__location__ "val=%d, val2=%d\n",
14325                                (int)val, (int)val2);
14326                         break;
14327                 }
14328
14329                 printf("val2=%d\r", val2);
14330
14331                 res = dbwrap_transaction_commit(db);
14332                 if (res != 0) {
14333                         printf(__location__ "transaction_commit failed\n");
14334                         break;
14335                 }
14336         }
14337
14338         TALLOC_FREE(db);
14339         return true;
14340 }
14341
14342 /*
14343  * Just a dummy test to be run under a debugger. There's no real way
14344  * to inspect the tevent_poll specific function from outside of
14345  * tevent_poll.c.
14346  */
14347
14348 static bool run_local_tevent_poll(int dummy)
14349 {
14350         struct tevent_context *ev;
14351         struct tevent_fd *fd1, *fd2;
14352         bool result = false;
14353
14354         ev = tevent_context_init_byname(NULL, "poll");
14355         if (ev == NULL) {
14356                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14357                 goto fail;
14358         }
14359
14360         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14361         if (fd1 == NULL) {
14362                 d_fprintf(stderr, "tevent_add_fd failed\n");
14363                 goto fail;
14364         }
14365         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14366         if (fd2 == NULL) {
14367                 d_fprintf(stderr, "tevent_add_fd failed\n");
14368                 goto fail;
14369         }
14370         TALLOC_FREE(fd2);
14371
14372         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14373         if (fd2 == NULL) {
14374                 d_fprintf(stderr, "tevent_add_fd failed\n");
14375                 goto fail;
14376         }
14377
14378         result = true;
14379 fail:
14380         TALLOC_FREE(ev);
14381         return result;
14382 }
14383
14384 static bool run_local_hex_encode_buf(int dummy)
14385 {
14386         char buf[17];
14387         uint8_t src[8];
14388         size_t i;
14389
14390         for (i=0; i<sizeof(src); i++) {
14391                 src[i] = i;
14392         }
14393         hex_encode_buf(buf, src, sizeof(src));
14394         if (strcmp(buf, "0001020304050607") != 0) {
14395                 return false;
14396         }
14397         hex_encode_buf(buf, NULL, 0);
14398         if (buf[0] != '\0') {
14399                 return false;
14400         }
14401         return true;
14402 }
14403
14404 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14405         "0.0.0.0",
14406         "::0",
14407         "1.2.3.1",
14408         "0.0.0.0",
14409         "0.0.0.0",
14410         "1.2.3.2",
14411         "1.2.3.3",
14412         "1.2.3.4",
14413         "1.2.3.5",
14414         "::0",
14415         "1.2.3.6",
14416         "1.2.3.7",
14417         "::0",
14418         "::0",
14419         "::0",
14420         "1.2.3.8",
14421         "1.2.3.9",
14422         "1.2.3.10",
14423         "1.2.3.11",
14424         "1.2.3.12",
14425         "1.2.3.13",
14426         "1001:1111:1111:1000:0:1111:1111:1111",
14427         "1.2.3.1",
14428         "1.2.3.2",
14429         "1.2.3.3",
14430         "1.2.3.12",
14431         "::0",
14432         "::0"
14433 };
14434
14435 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14436         "1.2.3.1",
14437         "1.2.3.2",
14438         "1.2.3.3",
14439         "1.2.3.4",
14440         "1.2.3.5",
14441         "1.2.3.6",
14442         "1.2.3.7",
14443         "1.2.3.8",
14444         "1.2.3.9",
14445         "1.2.3.10",
14446         "1.2.3.11",
14447         "1.2.3.12",
14448         "1.2.3.13",
14449         "1001:1111:1111:1000:0:1111:1111:1111"
14450 };
14451
14452 static bool run_local_remove_duplicate_addrs2(int dummy)
14453 {
14454         struct samba_sockaddr test_vector[28];
14455         size_t count, i;
14456
14457         /* Construct the sockaddr_storage test vector. */
14458         for (i = 0; i < 28; i++) {
14459                 struct addrinfo hints;
14460                 struct addrinfo *res = NULL;
14461                 int ret;
14462
14463                 memset(&hints, '\0', sizeof(hints));
14464                 hints.ai_flags = AI_NUMERICHOST;
14465                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14466                                 NULL,
14467                                 &hints,
14468                                 &res);
14469                 if (ret) {
14470                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14471                                 remove_duplicate_addrs2_test_strings_vector[i]);
14472                         return false;
14473                 }
14474                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14475                 memcpy(&test_vector[i].u.ss,
14476                         res->ai_addr,
14477                         res->ai_addrlen);
14478                 freeaddrinfo(res);
14479         }
14480
14481         count = remove_duplicate_addrs2(test_vector, i);
14482
14483         if (count != 14) {
14484                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14485                         count);
14486                 return false;
14487         }
14488
14489         for (i = 0; i < count; i++) {
14490                 char addr[INET6_ADDRSTRLEN];
14491
14492                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14493
14494                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14495                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14496                                 i,
14497                                 addr,
14498                                 remove_duplicate_addrs2_test_strings_result[i]);
14499                         return false;
14500                 }
14501         }
14502
14503         printf("run_local_remove_duplicate_addrs2: success\n");
14504         return true;
14505 }
14506
14507 static bool run_local_tdb_opener(int dummy)
14508 {
14509         TDB_CONTEXT *t;
14510         unsigned v = 0;
14511
14512         while (1) {
14513                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14514                              O_RDWR|O_CREAT, 0755);
14515                 if (t == NULL) {
14516                         perror("tdb_open failed");
14517                         return false;
14518                 }
14519                 tdb_close(t);
14520
14521                 v += 1;
14522                 printf("\r%u", v);
14523         }
14524         return true;
14525 }
14526
14527 static bool run_local_tdb_writer(int dummy)
14528 {
14529         TDB_CONTEXT *t;
14530         unsigned v = 0;
14531         TDB_DATA val;
14532
14533         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14534         if (t == 0) {
14535                 perror("tdb_open failed");
14536                 return 1;
14537         }
14538
14539         val.dptr = (uint8_t *)&v;
14540         val.dsize = sizeof(v);
14541
14542         while (1) {
14543                 TDB_DATA data;
14544                 int ret;
14545
14546                 ret = tdb_store(t, val, val, 0);
14547                 if (ret != 0) {
14548                         printf("%s\n", tdb_errorstr(t));
14549                 }
14550                 v += 1;
14551                 printf("\r%u", v);
14552
14553                 data = tdb_fetch(t, val);
14554                 if (data.dptr != NULL) {
14555                         SAFE_FREE(data.dptr);
14556                 }
14557         }
14558         return true;
14559 }
14560
14561 static bool run_local_canonicalize_path(int dummy)
14562 {
14563         const char *src[] = {
14564                         "/foo/..",
14565                         "/..",
14566                         "/foo/bar/../baz",
14567                         "/foo/././",
14568                         "/../foo",
14569                         ".././././",
14570                         ".././././../../../boo",
14571                         "./..",
14572                         "/",
14573                         "/../../",
14574                         "/foo/../",
14575                         "/./././",
14576                         "/./././.",
14577                         "/.../././.",
14578                         "/./././.foo",
14579                         "/./././.foo.",
14580                         "/./././foo.",
14581                         "/foo/bar/..",
14582                         "/foo/bar/../baz/",
14583                         "////////////////",
14584                         "/////////./././././.",
14585                         "/./.././../.boo/../baz",
14586                         "/a/component/path",
14587                         "/a/component/path/",
14588                         "/a/component/path/..",
14589                         "/a/component/../path/",
14590                         "///a/./././///component/../////path/",
14591                         NULL
14592                         };
14593         const char *dst[] = {
14594                         "/",
14595                         "/",
14596                         "/foo/baz",
14597                         "/foo",
14598                         "/foo",
14599                         "/",
14600                         "/boo",
14601                         "/",
14602                         "/",
14603                         "/",
14604                         "/",
14605                         "/",
14606                         "/",
14607                         "/...",
14608                         "/.foo",
14609                         "/.foo.",
14610                         "/foo.",
14611                         "/foo",
14612                         "/foo/baz",
14613                         "/",
14614                         "/",
14615                         "/baz",
14616                         "/a/component/path",
14617                         "/a/component/path",
14618                         "/a/component",
14619                         "/a/path",
14620                         "/a/path",
14621                         NULL
14622                         };
14623         unsigned int i;
14624
14625         for (i = 0; src[i] != NULL; i++) {
14626                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14627                 if (d == NULL) {
14628                         perror("talloc fail\n");
14629                         return false;
14630                 }
14631                 if (strcmp(d, dst[i]) != 0) {
14632                         d_fprintf(stderr,
14633                                 "canonicalize mismatch %s -> %s != %s",
14634                                 src[i], d, dst[i]);
14635                         return false;
14636                 }
14637                 talloc_free(d);
14638         }
14639         return true;
14640 }
14641
14642 static bool run_ign_bad_negprot(int dummy)
14643 {
14644         struct tevent_context *ev;
14645         struct tevent_req *req;
14646         struct smbXcli_conn *conn;
14647         struct sockaddr_storage ss;
14648         NTSTATUS status;
14649         int fd;
14650         bool ok;
14651
14652         printf("starting ignore bad negprot\n");
14653
14654         ok = resolve_name(host, &ss, 0x20, true);
14655         if (!ok) {
14656                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14657                 return false;
14658         }
14659
14660         status = open_socket_out(&ss, 445, 10000, &fd);
14661         if (!NT_STATUS_IS_OK(status)) {
14662                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14663                           nt_errstr(status));
14664                 return false;
14665         }
14666
14667         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14668                                    NULL, 0, NULL);
14669         if (conn == NULL) {
14670                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14671                 return false;
14672         }
14673
14674         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14675         if (NT_STATUS_IS_OK(status)) {
14676                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14677                 return false;
14678         }
14679
14680         ev = samba_tevent_context_init(talloc_tos());
14681         if (ev == NULL) {
14682                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14683                 return false;
14684         }
14685
14686         req = smb1cli_session_setup_nt1_send(
14687                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14688                 data_blob_null, data_blob_null, 0x40,
14689                 "Windows 2000 2195", "Windows 2000 5.0");
14690         if (req == NULL) {
14691                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14692                 return false;
14693         }
14694
14695         ok = tevent_req_poll_ntstatus(req, ev, &status);
14696         if (!ok) {
14697                 d_fprintf(stderr, "tevent_req_poll failed\n");
14698                 return false;
14699         }
14700
14701         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14702                                                 NULL, NULL);
14703         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14704                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14705                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14706                           nt_errstr(status));
14707                 return false;
14708         }
14709
14710         TALLOC_FREE(conn);
14711
14712         printf("starting ignore bad negprot\n");
14713
14714         return true;
14715 }
14716
14717 static double create_procs(bool (*fn)(int), bool *result)
14718 {
14719         int i, status;
14720         volatile pid_t *child_status;
14721         volatile bool *child_status_out;
14722         int synccount;
14723         int tries = 8;
14724         struct timeval start;
14725
14726         synccount = 0;
14727
14728         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14729         if (!child_status) {
14730                 printf("Failed to setup shared memory\n");
14731                 return -1;
14732         }
14733
14734         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14735         if (!child_status_out) {
14736                 printf("Failed to setup result status shared memory\n");
14737                 return -1;
14738         }
14739
14740         for (i = 0; i < torture_nprocs; i++) {
14741                 child_status[i] = 0;
14742                 child_status_out[i] = True;
14743         }
14744
14745         start = timeval_current();
14746
14747         for (i=0;i<torture_nprocs;i++) {
14748                 procnum = i;
14749                 if (fork() == 0) {
14750                         pid_t mypid = getpid();
14751                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14752
14753                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14754
14755                         while (1) {
14756                                 if (torture_open_connection(&current_cli, i)) break;
14757                                 if (tries-- == 0) {
14758                                         printf("pid %d failed to start\n", (int)getpid());
14759                                         _exit(1);
14760                                 }
14761                                 smb_msleep(10); 
14762                         }
14763
14764                         child_status[i] = getpid();
14765
14766                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14767
14768                         child_status_out[i] = fn(i);
14769                         _exit(0);
14770                 }
14771         }
14772
14773         do {
14774                 synccount = 0;
14775                 for (i=0;i<torture_nprocs;i++) {
14776                         if (child_status[i]) synccount++;
14777                 }
14778                 if (synccount == torture_nprocs) break;
14779                 smb_msleep(10);
14780         } while (timeval_elapsed(&start) < 30);
14781
14782         if (synccount != torture_nprocs) {
14783                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14784                 *result = False;
14785                 return timeval_elapsed(&start);
14786         }
14787
14788         /* start the client load */
14789         start = timeval_current();
14790
14791         for (i=0;i<torture_nprocs;i++) {
14792                 child_status[i] = 0;
14793         }
14794
14795         printf("%d clients started\n", torture_nprocs);
14796
14797         for (i=0;i<torture_nprocs;i++) {
14798                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14799         }
14800
14801         printf("\n");
14802
14803         for (i=0;i<torture_nprocs;i++) {
14804                 if (!child_status_out[i]) {
14805                         *result = False;
14806                 }
14807         }
14808         return timeval_elapsed(&start);
14809 }
14810
14811 #define FLAG_MULTIPROC 1
14812
14813 static struct {
14814         const char *name;
14815         bool (*fn)(int);
14816         unsigned flags;
14817 } torture_ops[] = {
14818         {
14819                 .name = "FDPASS",
14820                 .fn   = run_fdpasstest,
14821         },
14822         {
14823                 .name = "LOCK1",
14824                 .fn   = run_locktest1,
14825         },
14826         {
14827                 .name = "LOCK2",
14828                 .fn   =  run_locktest2,
14829         },
14830         {
14831                 .name = "LOCK3",
14832                 .fn   =  run_locktest3,
14833         },
14834         {
14835                 .name = "LOCK4",
14836                 .fn   =  run_locktest4,
14837         },
14838         {
14839                 .name = "LOCK5",
14840                 .fn   =  run_locktest5,
14841         },
14842         {
14843                 .name = "LOCK6",
14844                 .fn   =  run_locktest6,
14845         },
14846         {
14847                 .name = "LOCK7",
14848                 .fn   =  run_locktest7,
14849         },
14850         {
14851                 .name = "LOCK8",
14852                 .fn   =  run_locktest8,
14853         },
14854         {
14855                 .name = "LOCK9A",
14856                 .fn   =  run_locktest9a,
14857         },
14858         {
14859                 .name = "LOCK9B",
14860                 .fn   =  run_locktest9b,
14861         },
14862         {
14863                 .name = "LOCK10",
14864                 .fn   =  run_locktest10,
14865         },
14866         {
14867                 .name = "LOCK11",
14868                 .fn   =  run_locktest11,
14869         },
14870         {
14871                 .name = "LOCK12",
14872                 .fn   =  run_locktest12,
14873         },
14874         {
14875                 .name = "LOCK13",
14876                 .fn   =  run_locktest13,
14877         },
14878         {
14879                 .name = "UNLINK",
14880                 .fn   = run_unlinktest,
14881         },
14882         {
14883                 .name = "BROWSE",
14884                 .fn   = run_browsetest,
14885         },
14886         {
14887                 .name = "ATTR",
14888                 .fn   =   run_attrtest,
14889         },
14890         {
14891                 .name = "TRANS2",
14892                 .fn   = run_trans2test,
14893         },
14894         {
14895                 .name  = "MAXFID",
14896                 .fn    = run_maxfidtest,
14897                 .flags = FLAG_MULTIPROC,
14898         },
14899         {
14900                 .name  = "TORTURE",
14901                 .fn    = run_torture,
14902                 .flags = FLAG_MULTIPROC,
14903         },
14904         {
14905                 .name  = "RANDOMIPC",
14906                 .fn    = run_randomipc,
14907         },
14908         {
14909                 .name  = "NEGNOWAIT",
14910                 .fn    = run_negprot_nowait,
14911         },
14912         {
14913                 .name  = "NBENCH",
14914                 .fn    =  run_nbench,
14915         },
14916         {
14917                 .name  = "NBENCH2",
14918                 .fn    = run_nbench2,
14919         },
14920         {
14921                 .name  = "OPLOCK1",
14922                 .fn    =  run_oplock1,
14923         },
14924         {
14925                 .name  = "OPLOCK2",
14926                 .fn    =  run_oplock2,
14927         },
14928         {
14929                 .name  = "OPLOCK4",
14930                 .fn    =  run_oplock4,
14931         },
14932 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14933         {
14934                 .name  = "OPLOCK5",
14935                 .fn    =  run_oplock5,
14936         },
14937 #endif
14938         {
14939                 .name  = "DIR",
14940                 .fn    =  run_dirtest,
14941         },
14942         {
14943                 .name  = "DIR1",
14944                 .fn    =  run_dirtest1,
14945         },
14946         {
14947                 .name  = "DIR-CREATETIME",
14948                 .fn    =  run_dir_createtime,
14949         },
14950         {
14951                 .name  = "DENY1",
14952                 .fn    =  torture_denytest1,
14953         },
14954         {
14955                 .name  = "DENY2",
14956                 .fn    =  torture_denytest2,
14957         },
14958         {
14959                 .name  = "TCON",
14960                 .fn    =  run_tcon_test,
14961         },
14962         {
14963                 .name  = "TCONDEV",
14964                 .fn    =  run_tcon_devtype_test,
14965         },
14966         {
14967                 .name  = "RW1",
14968                 .fn    =  run_readwritetest,
14969         },
14970         {
14971                 .name  = "RW2",
14972                 .fn    =  run_readwritemulti,
14973                 .flags = FLAG_MULTIPROC
14974         },
14975         {
14976                 .name  = "RW3",
14977                 .fn    =  run_readwritelarge,
14978         },
14979         {
14980                 .name  = "RW-SIGNING",
14981                 .fn    =  run_readwritelarge_signtest,
14982         },
14983         {
14984                 .name  = "OPEN",
14985                 .fn    = run_opentest,
14986         },
14987         {
14988                 .name  = "POSIX",
14989                 .fn    = run_simple_posix_open_test,
14990         },
14991         {
14992                 .name  = "POSIX-APPEND",
14993                 .fn    = run_posix_append,
14994         },
14995         {
14996                 .name  = "POSIX-SYMLINK-ACL",
14997                 .fn    = run_acl_symlink_test,
14998         },
14999         {
15000                 .name  = "POSIX-SYMLINK-EA",
15001                 .fn    = run_ea_symlink_test,
15002         },
15003         {
15004                 .name  = "POSIX-STREAM-DELETE",
15005                 .fn    = run_posix_stream_delete,
15006         },
15007         {
15008                 .name  = "POSIX-OFD-LOCK",
15009                 .fn    = run_posix_ofd_lock_test,
15010         },
15011         {
15012                 .name  = "POSIX-BLOCKING-LOCK",
15013                 .fn    = run_posix_blocking_lock,
15014         },
15015         {
15016                 .name  = "POSIX-MKDIR",
15017                 .fn    = run_posix_mkdir_test,
15018         },
15019         {
15020                 .name  = "POSIX-ACL-OPLOCK",
15021                 .fn    = run_posix_acl_oplock_test,
15022         },
15023         {
15024                 .name  = "POSIX-ACL-SHAREROOT",
15025                 .fn    = run_posix_acl_shareroot_test,
15026         },
15027         {
15028                 .name  = "POSIX-LS-WILDCARD",
15029                 .fn    = run_posix_ls_wildcard_test,
15030         },
15031         {
15032                 .name  = "POSIX-LS-SINGLE",
15033                 .fn    = run_posix_ls_single_test,
15034         },
15035         {
15036                 .name  = "POSIX-READLINK",
15037                 .fn    = run_posix_readlink_test,
15038         },
15039         {
15040                 .name  = "POSIX-STAT",
15041                 .fn    = run_posix_stat_test,
15042         },
15043         {
15044                 .name  = "POSIX-SYMLINK-PARENT",
15045                 .fn    = run_posix_symlink_parent_test,
15046         },
15047         {
15048                 .name  = "POSIX-SYMLINK-CHMOD",
15049                 .fn    = run_posix_symlink_chmod_test,
15050         },
15051         {
15052                 .name  = "POSIX-SYMLINK-RENAME",
15053                 .fn    = run_posix_symlink_rename_test,
15054         },
15055         {
15056                 .name  = "POSIX-DIR-DEFAULT-ACL",
15057                 .fn    = run_posix_dir_default_acl_test,
15058         },
15059         {
15060                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15061                 .fn    = run_posix_symlink_getpathinfo_test,
15062         },
15063         {
15064                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15065                 .fn    = run_posix_symlink_setpathinfo_test,
15066         },
15067         {
15068                 .name  = "WINDOWS-BAD-SYMLINK",
15069                 .fn    = run_symlink_open_test,
15070         },
15071         {
15072                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15073                 .fn    = run_smb1_wild_mangle_unlink_test,
15074         },
15075         {
15076                 .name  = "SMB1-WILD-MANGLE-RENAME",
15077                 .fn    = run_smb1_wild_mangle_rename_test,
15078         },
15079         {
15080                 .name  = "CASE-INSENSITIVE-CREATE",
15081                 .fn    = run_case_insensitive_create,
15082         },
15083         {
15084                 .name  = "ASYNC-ECHO",
15085                 .fn    = run_async_echo,
15086         },
15087         {
15088                 .name  = "UID-REGRESSION-TEST",
15089                 .fn    = run_uid_regression_test,
15090         },
15091         {
15092                 .name  = "SHORTNAME-TEST",
15093                 .fn    = run_shortname_test,
15094         },
15095         {
15096                 .name  = "ADDRCHANGE",
15097                 .fn    = run_addrchange,
15098         },
15099 #if 1
15100         {
15101                 .name  = "OPENATTR",
15102                 .fn    = run_openattrtest,
15103         },
15104 #endif
15105         {
15106                 .name  = "XCOPY",
15107                 .fn    = run_xcopy,
15108         },
15109         {
15110                 .name  = "RENAME",
15111                 .fn    = run_rename,
15112         },
15113         {
15114                 .name  = "RENAME-ACCESS",
15115                 .fn    = run_rename_access,
15116         },
15117         {
15118                 .name  = "OWNER-RIGHTS",
15119                 .fn    = run_owner_rights,
15120         },
15121         {
15122                 .name  = "DELETE",
15123                 .fn    = run_deletetest,
15124         },
15125         {
15126                 .name  = "DELETE-STREAM",
15127                 .fn    = run_delete_stream,
15128         },
15129         {
15130                 .name  = "DELETE-PRINT",
15131                 .fn    = run_delete_print_test,
15132         },
15133         {
15134                 .name  = "DELETE-LN",
15135                 .fn    = run_deletetest_ln,
15136         },
15137         {
15138                 .name  = "PROPERTIES",
15139                 .fn    = run_properties,
15140         },
15141         {
15142                 .name  = "MANGLE",
15143                 .fn    = torture_mangle,
15144         },
15145         {
15146                 .name  = "MANGLE1",
15147                 .fn    = run_mangle1,
15148         },
15149         {
15150                 .name  = "MANGLE-ILLEGAL",
15151                 .fn    = run_mangle_illegal,
15152         },
15153         {
15154                 .name  = "W2K",
15155                 .fn    = run_w2ktest,
15156         },
15157         {
15158                 .name  = "TRANS2SCAN",
15159                 .fn    = torture_trans2_scan,
15160         },
15161         {
15162                 .name  = "NTTRANSSCAN",
15163                 .fn    = torture_nttrans_scan,
15164         },
15165         {
15166                 .name  = "UTABLE",
15167                 .fn    = torture_utable,
15168         },
15169         {
15170                 .name  = "CASETABLE",
15171                 .fn    = torture_casetable,
15172         },
15173         {
15174                 .name  = "ERRMAPEXTRACT",
15175                 .fn    = run_error_map_extract,
15176         },
15177         {
15178                 .name  = "PIPE_NUMBER",
15179                 .fn    = run_pipe_number,
15180         },
15181         {
15182                 .name  = "TCON2",
15183                 .fn    =  run_tcon2_test,
15184         },
15185         {
15186                 .name  = "IOCTL",
15187                 .fn    =  torture_ioctl_test,
15188         },
15189         {
15190                 .name  = "CHKPATH",
15191                 .fn    =  torture_chkpath_test,
15192         },
15193         {
15194                 .name  = "FDSESS",
15195                 .fn    = run_fdsesstest,
15196         },
15197         {
15198                 .name  = "EATEST",
15199                 .fn    = run_eatest,
15200         },
15201         {
15202                 .name  = "SESSSETUP_BENCH",
15203                 .fn    = run_sesssetup_bench,
15204         },
15205         {
15206                 .name  = "CHAIN1",
15207                 .fn    = run_chain1,
15208         },
15209         {
15210                 .name  = "CHAIN2",
15211                 .fn    = run_chain2,
15212         },
15213         {
15214                 .name  = "CHAIN3",
15215                 .fn    = run_chain3,
15216         },
15217         {
15218                 .name  = "WINDOWS-WRITE",
15219                 .fn    = run_windows_write,
15220         },
15221         {
15222                 .name  = "LARGE_READX",
15223                 .fn    = run_large_readx,
15224         },
15225         {
15226                 .name  = "MSDFS-ATTRIBUTE",
15227                 .fn    = run_msdfs_attribute,
15228         },
15229         {
15230                 .name  = "NTTRANS-CREATE",
15231                 .fn    = run_nttrans_create,
15232         },
15233         {
15234                 .name  = "NTTRANS-FSCTL",
15235                 .fn    = run_nttrans_fsctl,
15236         },
15237         {
15238                 .name  = "CLI_ECHO",
15239                 .fn    = run_cli_echo,
15240         },
15241         {
15242                 .name  = "CLI_SPLICE",
15243                 .fn    = run_cli_splice,
15244         },
15245         {
15246                 .name  = "TLDAP",
15247                 .fn    = run_tldap,
15248         },
15249         {
15250                 .name  = "STREAMERROR",
15251                 .fn    = run_streamerror,
15252         },
15253         {
15254                 .name  = "NOTIFY-BENCH",
15255                 .fn    = run_notify_bench,
15256         },
15257         {
15258                 .name  = "NOTIFY-BENCH2",
15259                 .fn    = run_notify_bench2,
15260         },
15261         {
15262                 .name  = "NOTIFY-BENCH3",
15263                 .fn    = run_notify_bench3,
15264         },
15265         {
15266                 .name  = "BAD-NBT-SESSION",
15267                 .fn    = run_bad_nbt_session,
15268         },
15269         {
15270                 .name  = "IGN-BAD-NEGPROT",
15271                 .fn    = run_ign_bad_negprot,
15272         },
15273         {
15274                 .name  = "SMB-ANY-CONNECT",
15275                 .fn    = run_smb_any_connect,
15276         },
15277         {
15278                 .name  = "NOTIFY-ONLINE",
15279                 .fn    = run_notify_online,
15280         },
15281         {
15282                 .name  = "SMB2-BASIC",
15283                 .fn    = run_smb2_basic,
15284         },
15285         {
15286                 .name  = "SMB2-NEGPROT",
15287                 .fn    = run_smb2_negprot,
15288         },
15289         {
15290                 .name  = "SMB2-ANONYMOUS",
15291                 .fn    = run_smb2_anonymous,
15292         },
15293         {
15294                 .name  = "SMB2-SESSION-RECONNECT",
15295                 .fn    = run_smb2_session_reconnect,
15296         },
15297         {
15298                 .name  = "SMB2-TCON-DEPENDENCE",
15299                 .fn    = run_smb2_tcon_dependence,
15300         },
15301         {
15302                 .name  = "SMB2-MULTI-CHANNEL",
15303                 .fn    = run_smb2_multi_channel,
15304         },
15305         {
15306                 .name  = "SMB2-SESSION-REAUTH",
15307                 .fn    = run_smb2_session_reauth,
15308         },
15309         {
15310                 .name  = "SMB2-FTRUNCATE",
15311                 .fn    = run_smb2_ftruncate,
15312         },
15313         {
15314                 .name  = "SMB2-DIR-FSYNC",
15315                 .fn    = run_smb2_dir_fsync,
15316         },
15317         {
15318                 .name  = "SMB2-PATH-SLASH",
15319                 .fn    = run_smb2_path_slash,
15320         },
15321         {
15322                 .name  = "SMB1-SYSTEM-SECURITY",
15323                 .fn    = run_smb1_system_security,
15324         },
15325         {
15326                 .name  = "SMB2-SACL",
15327                 .fn    = run_smb2_sacl,
15328         },
15329         {
15330                 .name  = "SMB2-QUOTA1",
15331                 .fn    = run_smb2_quota1,
15332         },
15333         {
15334                 .name  = "SMB2-STREAM-ACL",
15335                 .fn    = run_smb2_stream_acl,
15336         },
15337         {
15338                 .name  = "SMB2-LIST-DIR-ASYNC",
15339                 .fn    = run_list_dir_async_test,
15340         },
15341         {
15342                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15343                 .fn    = run_delete_on_close_non_empty,
15344         },
15345         {
15346                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15347                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15348         },
15349         {
15350                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15351                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15352         },
15353         {
15354                 .name  = "CLEANUP1",
15355                 .fn    = run_cleanup1,
15356         },
15357         {
15358                 .name  = "CLEANUP2",
15359                 .fn    = run_cleanup2,
15360         },
15361         {
15362                 .name  = "CLEANUP4",
15363                 .fn    = run_cleanup4,
15364         },
15365         {
15366                 .name  = "OPLOCK-CANCEL",
15367                 .fn    = run_oplock_cancel,
15368         },
15369         {
15370                 .name  = "PIDHIGH",
15371                 .fn    = run_pidhigh,
15372         },
15373         {
15374                 .name  = "LOCAL-SUBSTITUTE",
15375                 .fn    = run_local_substitute,
15376         },
15377         {
15378                 .name  = "LOCAL-GENCACHE",
15379                 .fn    = run_local_gencache,
15380         },
15381         {
15382                 .name  = "LOCAL-DBWRAP-WATCH1",
15383                 .fn    = run_dbwrap_watch1,
15384         },
15385         {
15386                 .name  = "LOCAL-DBWRAP-WATCH2",
15387                 .fn    = run_dbwrap_watch2,
15388         },
15389         {
15390                 .name  = "LOCAL-DBWRAP-WATCH3",
15391                 .fn    = run_dbwrap_watch3,
15392         },
15393         {
15394                 .name  = "LOCAL-DBWRAP-WATCH4",
15395                 .fn    = run_dbwrap_watch4,
15396         },
15397         {
15398                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
15399                 .fn    = run_dbwrap_do_locked1,
15400         },
15401         {
15402                 .name  = "LOCAL-MESSAGING-READ1",
15403                 .fn    = run_messaging_read1,
15404         },
15405         {
15406                 .name  = "LOCAL-MESSAGING-READ2",
15407                 .fn    = run_messaging_read2,
15408         },
15409         {
15410                 .name  = "LOCAL-MESSAGING-READ3",
15411                 .fn    = run_messaging_read3,
15412         },
15413         {
15414                 .name  = "LOCAL-MESSAGING-READ4",
15415                 .fn    = run_messaging_read4,
15416         },
15417         {
15418                 .name  = "LOCAL-MESSAGING-FDPASS1",
15419                 .fn    = run_messaging_fdpass1,
15420         },
15421         {
15422                 .name  = "LOCAL-MESSAGING-FDPASS2",
15423                 .fn    = run_messaging_fdpass2,
15424         },
15425         {
15426                 .name  = "LOCAL-MESSAGING-FDPASS2a",
15427                 .fn    = run_messaging_fdpass2a,
15428         },
15429         {
15430                 .name  = "LOCAL-MESSAGING-FDPASS2b",
15431                 .fn    = run_messaging_fdpass2b,
15432         },
15433         {
15434                 .name  = "LOCAL-MESSAGING-SEND-ALL",
15435                 .fn    = run_messaging_send_all,
15436         },
15437         {
15438                 .name  = "LOCAL-BASE64",
15439                 .fn    = run_local_base64,
15440         },
15441         {
15442                 .name  = "LOCAL-RBTREE",
15443                 .fn    = run_local_rbtree,
15444         },
15445         {
15446                 .name  = "LOCAL-MEMCACHE",
15447                 .fn    = run_local_memcache,
15448         },
15449         {
15450                 .name  = "LOCAL-STREAM-NAME",
15451                 .fn    = run_local_stream_name,
15452         },
15453         {
15454                 .name  = "LOCAL-STR-MATCH-MSWILD",
15455                 .fn    = run_str_match_mswild,
15456         },
15457         {
15458                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
15459                 .fn    = run_str_match_regex_sub1,
15460         },
15461         {
15462                 .name  = "WBCLIENT-MULTI-PING",
15463                 .fn    = run_wbclient_multi_ping,
15464         },
15465         {
15466                 .name  = "LOCAL-string_to_sid",
15467                 .fn    = run_local_string_to_sid,
15468         },
15469         {
15470                 .name  = "LOCAL-sid_to_string",
15471                 .fn    = run_local_sid_to_string,
15472         },
15473         {
15474                 .name  = "LOCAL-binary_to_sid",
15475                 .fn    = run_local_binary_to_sid,
15476         },
15477         {
15478                 .name  = "LOCAL-DBTRANS",
15479                 .fn    = run_local_dbtrans,
15480         },
15481         {
15482                 .name  = "LOCAL-TEVENT-POLL",
15483                 .fn    = run_local_tevent_poll,
15484         },
15485         {
15486                 .name  = "LOCAL-CONVERT-STRING",
15487                 .fn    = run_local_convert_string,
15488         },
15489         {
15490                 .name  = "LOCAL-CONV-AUTH-INFO",
15491                 .fn    = run_local_conv_auth_info,
15492         },
15493         {
15494                 .name  = "LOCAL-hex_encode_buf",
15495                 .fn    = run_local_hex_encode_buf,
15496         },
15497         {
15498                 .name  = "LOCAL-IDMAP-TDB-COMMON",
15499                 .fn    = run_idmap_tdb_common_test,
15500         },
15501         {
15502                 .name  = "LOCAL-remove_duplicate_addrs2",
15503                 .fn    = run_local_remove_duplicate_addrs2,
15504         },
15505         {
15506                 .name  = "local-tdb-opener",
15507                 .fn    = run_local_tdb_opener,
15508         },
15509         {
15510                 .name  = "local-tdb-writer",
15511                 .fn    = run_local_tdb_writer,
15512         },
15513         {
15514                 .name  = "LOCAL-DBWRAP-CTDB1",
15515                 .fn    = run_local_dbwrap_ctdb1,
15516         },
15517         {
15518                 .name  = "LOCAL-BENCH-PTHREADPOOL",
15519                 .fn    = run_bench_pthreadpool,
15520         },
15521         {
15522                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
15523                 .fn    = run_pthreadpool_tevent,
15524         },
15525         {
15526                 .name  = "LOCAL-G-LOCK1",
15527                 .fn    = run_g_lock1,
15528         },
15529         {
15530                 .name  = "LOCAL-G-LOCK2",
15531                 .fn    = run_g_lock2,
15532         },
15533         {
15534                 .name  = "LOCAL-G-LOCK3",
15535                 .fn    = run_g_lock3,
15536         },
15537         {
15538                 .name  = "LOCAL-G-LOCK4",
15539                 .fn    = run_g_lock4,
15540         },
15541         {
15542                 .name  = "LOCAL-G-LOCK4A",
15543                 .fn    = run_g_lock4a,
15544         },
15545         {
15546                 .name  = "LOCAL-G-LOCK5",
15547                 .fn    = run_g_lock5,
15548         },
15549         {
15550                 .name  = "LOCAL-G-LOCK6",
15551                 .fn    = run_g_lock6,
15552         },
15553         {
15554                 .name  = "LOCAL-G-LOCK7",
15555                 .fn    = run_g_lock7,
15556         },
15557         {
15558                 .name  = "LOCAL-G-LOCK8",
15559                 .fn    = run_g_lock8,
15560         },
15561         {
15562                 .name  = "LOCAL-G-LOCK-PING-PONG",
15563                 .fn    = run_g_lock_ping_pong,
15564         },
15565         {
15566                 .name  = "LOCAL-CANONICALIZE-PATH",
15567                 .fn    = run_local_canonicalize_path,
15568         },
15569         {
15570                 .name  = "LOCAL-NAMEMAP-CACHE1",
15571                 .fn    = run_local_namemap_cache1,
15572         },
15573         {
15574                 .name  = "LOCAL-IDMAP-CACHE1",
15575                 .fn    = run_local_idmap_cache1,
15576         },
15577         {
15578                 .name  = "qpathinfo-bufsize",
15579                 .fn    = run_qpathinfo_bufsize,
15580         },
15581         {
15582                 .name  = "hide-new-files-timeout",
15583                 .fn    = run_hidenewfiles,
15584         },
15585 #ifdef CLUSTER_SUPPORT
15586         {
15587                 .name  = "ctdbd-conn1",
15588                 .fn    = run_ctdbd_conn1,
15589         },
15590 #endif
15591         {
15592                 .name  = "readdir-timestamp",
15593                 .fn    = run_readdir_timestamp,
15594         },
15595         {
15596                 .name = NULL,
15597         },
15598 };
15599
15600 /****************************************************************************
15601 run a specified test or "ALL"
15602 ****************************************************************************/
15603 static bool run_test(const char *name)
15604 {
15605         bool ret = True;
15606         bool result = True;
15607         bool found = False;
15608         int i;
15609         double t;
15610         if (strequal(name,"ALL")) {
15611                 for (i=0;torture_ops[i].name;i++) {
15612                         run_test(torture_ops[i].name);
15613                 }
15614                 found = True;
15615         }
15616
15617         for (i=0;torture_ops[i].name;i++) {
15618                 fstr_sprintf(randomfname, "\\XX%x", 
15619                          (unsigned)random());
15620
15621                 if (strequal(name, torture_ops[i].name)) {
15622                         found = True;
15623                         printf("Running %s\n", name);
15624                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
15625                                 t = create_procs(torture_ops[i].fn, &result);
15626                                 if (!result) { 
15627                                         ret = False;
15628                                         printf("TEST %s FAILED!\n", name);
15629                                 }
15630                         } else {
15631                                 struct timeval start;
15632                                 start = timeval_current();
15633                                 if (!torture_ops[i].fn(0)) {
15634                                         ret = False;
15635                                         printf("TEST %s FAILED!\n", name);
15636                                 }
15637                                 t = timeval_elapsed(&start);
15638                         }
15639                         printf("%s took %g secs\n\n", name, t);
15640                 }
15641         }
15642
15643         if (!found) {
15644                 printf("Did not find a test named %s\n", name);
15645                 ret = False;
15646         }
15647
15648         return ret;
15649 }
15650
15651
15652 static void usage(void)
15653 {
15654         int i;
15655
15656         printf("WARNING samba4 test suite is much more complete nowadays.\n");
15657         printf("Please use samba4 torture.\n\n");
15658
15659         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15660
15661         printf("\t-d debuglevel\n");
15662         printf("\t-U user%%pass\n");
15663         printf("\t-k                    use kerberos\n");
15664         printf("\t-N numprocs\n");
15665         printf("\t-n my_netbios_name\n");
15666         printf("\t-W workgroup\n");
15667         printf("\t-o num_operations\n");
15668         printf("\t-O socket_options\n");
15669         printf("\t-m maximum protocol\n");
15670         printf("\t-L use oplocks\n");
15671         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
15672         printf("\t-A showall\n");
15673         printf("\t-p port\n");
15674         printf("\t-s seed\n");
15675         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
15676         printf("\t-f filename           filename to test\n");
15677         printf("\t-e                    encrypt\n");
15678         printf("\n\n");
15679
15680         printf("tests are:");
15681         for (i=0;torture_ops[i].name;i++) {
15682                 printf(" %s", torture_ops[i].name);
15683         }
15684         printf("\n");
15685
15686         printf("default test is ALL\n");
15687
15688         exit(1);
15689 }
15690
15691 /****************************************************************************
15692   main program
15693 ****************************************************************************/
15694  int main(int argc,char *argv[])
15695 {
15696         int opt, i;
15697         char *p;
15698         int gotuser = 0;
15699         int gotpass = 0;
15700         bool correct = True;
15701         TALLOC_CTX *frame = talloc_stackframe();
15702         int seed = time(NULL);
15703
15704 #ifdef HAVE_SETBUFFER
15705         setbuffer(stdout, NULL, 0);
15706 #endif
15707
15708         setup_logging("smbtorture", DEBUG_STDOUT);
15709
15710         smb_init_locale();
15711         fault_setup();
15712
15713         if (is_default_dyn_CONFIGFILE()) {
15714                 if(getenv("SMB_CONF_PATH")) {
15715                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15716                 }
15717         }
15718         lp_load_global(get_dyn_CONFIGFILE());
15719         load_interfaces();
15720
15721         if (argc < 2) {
15722                 usage();
15723         }
15724
15725         for(p = argv[1]; *p; p++)
15726           if(*p == '\\')
15727             *p = '/';
15728
15729         if (strncmp(argv[1], "//", 2)) {
15730                 usage();
15731         }
15732
15733         fstrcpy(host, &argv[1][2]);
15734         p = strchr_m(&host[2],'/');
15735         if (!p) {
15736                 usage();
15737         }
15738         *p = 0;
15739         fstrcpy(share, p+1);
15740
15741         fstrcpy(myname, get_myname(talloc_tos()));
15742         if (!*myname) {
15743                 fprintf(stderr, "Failed to get my hostname.\n");
15744                 return 1;
15745         }
15746
15747         if (*username == 0 && getenv("LOGNAME")) {
15748           fstrcpy(username,getenv("LOGNAME"));
15749         }
15750
15751         argc--;
15752         argv++;
15753
15754         fstrcpy(workgroup, lp_workgroup());
15755
15756         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15757                != EOF) {
15758                 switch (opt) {
15759                 case 'p':
15760                         port_to_use = atoi(optarg);
15761                         break;
15762                 case 's':
15763                         seed = atoi(optarg);
15764                         break;
15765                 case 'W':
15766                         fstrcpy(workgroup,optarg);
15767                         break;
15768                 case 'm':
15769                         lp_set_cmdline("client max protocol", optarg);
15770                         break;
15771                 case 'N':
15772                         torture_nprocs = atoi(optarg);
15773                         break;
15774                 case 'o':
15775                         torture_numops = atoi(optarg);
15776                         break;
15777                 case 'd':
15778                         lp_set_cmdline("log level", optarg);
15779                         break;
15780                 case 'O':
15781                         sockops = optarg;
15782                         break;
15783                 case 'L':
15784                         use_oplocks = True;
15785                         break;
15786                 case 'l':
15787                         local_path = optarg;
15788                         break;
15789                 case 'A':
15790                         torture_showall = True;
15791                         break;
15792                 case 'n':
15793                         fstrcpy(myname, optarg);
15794                         break;
15795                 case 'c':
15796                         client_txt = optarg;
15797                         break;
15798                 case 'e':
15799                         do_encrypt = true;
15800                         break;
15801                 case 'k':
15802 #ifdef HAVE_KRB5
15803                         use_kerberos = True;
15804 #else
15805                         d_printf("No kerberos support compiled in\n");
15806                         exit(1);
15807 #endif
15808                         break;
15809                 case 'U':
15810                         gotuser = 1;
15811                         fstrcpy(username,optarg);
15812                         p = strchr_m(username,'%');
15813                         if (p) {
15814                                 *p = 0;
15815                                 fstrcpy(password, p+1);
15816                                 gotpass = 1;
15817                         }
15818                         break;
15819                 case 'b':
15820                         fstrcpy(multishare_conn_fname, optarg);
15821                         use_multishare_conn = True;
15822                         break;
15823                 case 'B':
15824                         torture_blocksize = atoi(optarg);
15825                         break;
15826                 case 'f':
15827                         test_filename = SMB_STRDUP(optarg);
15828                         break;
15829                 default:
15830                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15831                         usage();
15832                 }
15833         }
15834
15835         d_printf("using seed %d\n", seed);
15836
15837         srandom(seed);
15838
15839         if(use_kerberos && !gotuser) gotpass = True;
15840
15841         while (!gotpass) {
15842                 char pwd[256] = {0};
15843                 int rc;
15844
15845                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15846                 if (rc == 0) {
15847                         fstrcpy(password, pwd);
15848                         gotpass = 1;
15849                 }
15850         }
15851
15852         printf("host=%s share=%s user=%s myname=%s\n", 
15853                host, share, username, myname);
15854
15855         torture_creds = cli_session_creds_init(frame,
15856                                                username,
15857                                                workgroup,
15858                                                NULL, /* realm */
15859                                                password,
15860                                                use_kerberos,
15861                                                false, /* fallback_after_kerberos */
15862                                                false, /* use_ccache */
15863                                                false); /* password_is_nt_hash */
15864         if (torture_creds == NULL) {
15865                 d_printf("cli_session_creds_init() failed.\n");
15866                 exit(1);
15867         }
15868
15869         if (argc == optind) {
15870                 correct = run_test("ALL");
15871         } else {
15872                 for (i=optind;i<argc;i++) {
15873                         if (!run_test(argv[i])) {
15874                                 correct = False;
15875                         }
15876                 }
15877         }
15878
15879         TALLOC_FREE(frame);
15880
15881         if (correct) {
15882                 return(0);
15883         } else {
15884                 return(1);
15885         }
15886 }