smbtorture3: Avoid an "else"
[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(
3957                         ev,
3958                         ev,
3959                         cli->conn,
3960                         cli->timeout,
3961                         PROTOCOL_CORE,
3962                         PROTOCOL_NT1,
3963                         0,
3964                         NULL);
3965                 if (req == NULL) {
3966                         TALLOC_FREE(ev);
3967                         return false;
3968                 }
3969                 if (!tevent_req_poll(req, ev)) {
3970                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3971                                   strerror(errno));
3972                         TALLOC_FREE(ev);
3973                         return false;
3974                 }
3975                 TALLOC_FREE(req);
3976         }
3977
3978         if (torture_close_connection(cli)) {
3979                 correct = False;
3980         }
3981
3982         printf("finished negprot nowait test\n");
3983
3984         return correct;
3985 }
3986
3987 /* send smb negprot commands, not reading the response */
3988 static bool run_bad_nbt_session(int dummy)
3989 {
3990         struct nmb_name called, calling;
3991         struct sockaddr_storage ss;
3992         NTSTATUS status;
3993         int fd;
3994         bool ret;
3995
3996         printf("starting bad nbt session test\n");
3997
3998         make_nmb_name(&calling, myname, 0x0);
3999         make_nmb_name(&called , host, 0x20);
4000
4001         if (!resolve_name(host, &ss, 0x20, true)) {
4002                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4003                 return false;
4004         }
4005
4006         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4007         if (!NT_STATUS_IS_OK(status)) {
4008                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4009                           nt_errstr(status));
4010                 return false;
4011         }
4012
4013         ret = cli_bad_session_request(fd, &calling, &called);
4014         close(fd);
4015         if (!ret) {
4016                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4017                           nt_errstr(status));
4018                 return false;
4019         }
4020
4021         printf("finished bad nbt session test\n");
4022         return true;
4023 }
4024
4025 /* send random IPC commands */
4026 static bool run_randomipc(int dummy)
4027 {
4028         char *rparam = NULL;
4029         char *rdata = NULL;
4030         unsigned int rdrcnt,rprcnt;
4031         char param[1024];
4032         int api, param_len, i;
4033         struct cli_state *cli;
4034         bool correct = True;
4035         int count = 50000;
4036
4037         printf("starting random ipc test\n");
4038
4039         if (!torture_open_connection(&cli, 0)) {
4040                 return False;
4041         }
4042
4043         for (i=0;i<count;i++) {
4044                 api = sys_random() % 500;
4045                 param_len = (sys_random() % 64);
4046
4047                 rand_buf(param, param_len);
4048
4049                 SSVAL(param,0,api); 
4050
4051                 cli_api(cli, 
4052                         param, param_len, 8,  
4053                         NULL, 0, CLI_BUFFER_SIZE,
4054                         &rparam, &rprcnt,     
4055                         &rdata, &rdrcnt);
4056                 if (i % 100 == 0) {
4057                         printf("%d/%d\r", i,count);
4058                 }
4059         }
4060         printf("%d/%d\n", i, count);
4061
4062         if (!torture_close_connection(cli)) {
4063                 correct = False;
4064         }
4065
4066         SAFE_FREE(rparam);
4067         SAFE_FREE(rdata);
4068
4069         printf("finished random ipc test\n");
4070
4071         return correct;
4072 }
4073
4074
4075
4076 static void browse_callback(const char *sname, uint32_t stype,
4077                             const char *comment, void *state)
4078 {
4079         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4080 }
4081
4082
4083
4084 /*
4085   This test checks the browse list code
4086
4087 */
4088 static bool run_browsetest(int dummy)
4089 {
4090         static struct cli_state *cli;
4091         bool correct = True;
4092
4093         printf("starting browse test\n");
4094
4095         if (!torture_open_connection(&cli, 0)) {
4096                 return False;
4097         }
4098
4099         printf("domain list:\n");
4100         cli_NetServerEnum(cli, cli->server_domain, 
4101                           SV_TYPE_DOMAIN_ENUM,
4102                           browse_callback, NULL);
4103
4104         printf("machine list:\n");
4105         cli_NetServerEnum(cli, cli->server_domain, 
4106                           SV_TYPE_ALL,
4107                           browse_callback, NULL);
4108
4109         if (!torture_close_connection(cli)) {
4110                 correct = False;
4111         }
4112
4113         printf("browse test finished\n");
4114
4115         return correct;
4116
4117 }
4118
4119 static bool check_attributes(struct cli_state *cli,
4120                                 const char *fname,
4121                                 uint32_t expected_attrs)
4122 {
4123         uint32_t attrs = 0;
4124         NTSTATUS status = cli_getatr(cli,
4125                                 fname,
4126                                 &attrs,
4127                                 NULL,
4128                                 NULL);
4129         if (!NT_STATUS_IS_OK(status)) {
4130                 printf("cli_getatr failed with %s\n",
4131                         nt_errstr(status));
4132                 return false;
4133         }
4134         if (attrs != expected_attrs) {
4135                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4136                         (unsigned int)attrs,
4137                         (unsigned int)expected_attrs);
4138                 return false;
4139         }
4140         return true;
4141 }
4142
4143 /*
4144   This checks how the getatr calls works
4145 */
4146 static bool run_attrtest(int dummy)
4147 {
4148         struct cli_state *cli;
4149         uint16_t fnum;
4150         time_t t, t2;
4151         const char *fname = "\\attrib123456789.tst";
4152         bool correct = True;
4153         NTSTATUS status;
4154
4155         printf("starting attrib test\n");
4156
4157         if (!torture_open_connection(&cli, 0)) {
4158                 return False;
4159         }
4160
4161         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4162         status = cli_unlink(cli, fname, 0x20000);
4163         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4164                 correct = false;
4165                 goto out;
4166         }
4167
4168         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4169         cli_openx(cli, fname, 
4170                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4171         cli_close(cli, fnum);
4172
4173         status = cli_getatr(cli, fname, NULL, NULL, &t);
4174         if (!NT_STATUS_IS_OK(status)) {
4175                 printf("getatr failed (%s)\n", nt_errstr(status));
4176                 correct = False;
4177         }
4178
4179         if (labs(t - time(NULL)) > 60*60*24*10) {
4180                 printf("ERROR: SMBgetatr bug. time is %s",
4181                        ctime(&t));
4182                 t = time(NULL);
4183                 correct = True;
4184         }
4185
4186         t2 = t-60*60*24; /* 1 day ago */
4187
4188         /* Ensure we can't set with out-of-range (unknown) attribute. */
4189         status = cli_setatr(cli, fname, 0x20000, t2);
4190         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4191                 correct = false;
4192                 goto out;
4193         }
4194
4195         status = cli_setatr(cli, fname, 0, t2);
4196         if (!NT_STATUS_IS_OK(status)) {
4197                 printf("setatr failed (%s)\n", nt_errstr(status));
4198                 correct = True;
4199         }
4200
4201         status = cli_getatr(cli, fname, NULL, NULL, &t);
4202         if (!NT_STATUS_IS_OK(status)) {
4203                 printf("getatr failed (%s)\n", nt_errstr(status));
4204                 correct = True;
4205         }
4206
4207         if (t != t2) {
4208                 printf("ERROR: getatr/setatr bug. times are\n%s",
4209                        ctime(&t));
4210                 printf("%s", ctime(&t2));
4211                 correct = True;
4212         }
4213
4214         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4215
4216         /* Check cli_setpathinfo_ext() */
4217         /* Re-create the file. */
4218         status = cli_openx(cli, fname,
4219                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4220         if (!NT_STATUS_IS_OK(status)) {
4221                 printf("Failed to recreate %s (%s)\n",
4222                         fname, nt_errstr(status));
4223                 correct = false;
4224         }
4225         cli_close(cli, fnum);
4226
4227         status = cli_setpathinfo_ext(
4228                 cli,
4229                 fname,
4230                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4231                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4232                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4233                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4234                 FILE_ATTRIBUTE_SYSTEM |
4235                 FILE_ATTRIBUTE_HIDDEN |
4236                 FILE_ATTRIBUTE_READONLY);
4237         if (!NT_STATUS_IS_OK(status)) {
4238                 printf("cli_setpathinfo_ext failed with %s\n",
4239                         nt_errstr(status));
4240                 correct = false;
4241         }
4242
4243         /* Check attributes are correct. */
4244         correct = check_attributes(cli,
4245                         fname,
4246                         FILE_ATTRIBUTE_SYSTEM |
4247                         FILE_ATTRIBUTE_HIDDEN |
4248                         FILE_ATTRIBUTE_READONLY);
4249         if (correct == false) {
4250                 goto out;
4251         }
4252
4253         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4254         status = cli_setpathinfo_ext(
4255                 cli,
4256                 fname,
4257                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4258                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4259                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4260                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4261                 FILE_ATTRIBUTE_NORMAL);
4262         if (!NT_STATUS_IS_OK(status)) {
4263                 printf("cli_setpathinfo_ext failed with %s\n",
4264                         nt_errstr(status));
4265                 correct = false;
4266         }
4267
4268         /* Check attributes are correct. */
4269         correct = check_attributes(cli,
4270                         fname,
4271                         FILE_ATTRIBUTE_SYSTEM |
4272                         FILE_ATTRIBUTE_HIDDEN |
4273                         FILE_ATTRIBUTE_READONLY);
4274         if (correct == false) {
4275                 goto out;
4276         }
4277
4278         /* Setting to (uint16_t)-1 should also be ignored. */
4279         status = cli_setpathinfo_ext(
4280                 cli,
4281                 fname,
4282                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4283                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4284                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4285                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4286                 (uint32_t)-1);
4287         if (!NT_STATUS_IS_OK(status)) {
4288                 printf("cli_setpathinfo_ext failed with %s\n",
4289                         nt_errstr(status));
4290                 correct = false;
4291         }
4292
4293         /* Check attributes are correct. */
4294         correct = check_attributes(cli,
4295                         fname,
4296                         FILE_ATTRIBUTE_SYSTEM |
4297                         FILE_ATTRIBUTE_HIDDEN |
4298                         FILE_ATTRIBUTE_READONLY);
4299         if (correct == false) {
4300                 goto out;
4301         }
4302
4303         /* Setting to 0 should clear them all. */
4304         status = cli_setpathinfo_ext(
4305                 cli,
4306                 fname,
4307                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4308                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4309                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4310                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4311                 0);
4312         if (!NT_STATUS_IS_OK(status)) {
4313                 printf("cli_setpathinfo_ext failed with %s\n",
4314                         nt_errstr(status));
4315                 correct = false;
4316         }
4317
4318         /* Check attributes are correct. */
4319         correct = check_attributes(cli,
4320                         fname,
4321                         FILE_ATTRIBUTE_NORMAL);
4322         if (correct == false) {
4323                 goto out;
4324         }
4325
4326   out:
4327
4328         cli_unlink(cli,
4329                 fname,
4330                 FILE_ATTRIBUTE_SYSTEM |
4331                 FILE_ATTRIBUTE_HIDDEN|
4332                 FILE_ATTRIBUTE_READONLY);
4333
4334         if (!torture_close_connection(cli)) {
4335                 correct = False;
4336         }
4337
4338         printf("attrib test finished\n");
4339
4340         return correct;
4341 }
4342
4343 static NTSTATUS cli_qfilename(
4344         struct cli_state *cli,
4345         uint16_t fnum,
4346         TALLOC_CTX *mem_ctx,
4347         char **_name)
4348 {
4349         uint16_t recv_flags2;
4350         uint8_t *rdata;
4351         uint32_t num_rdata;
4352         NTSTATUS status;
4353         char *name = NULL;
4354         uint32_t namelen;
4355
4356         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4357                                SMB_QUERY_FILE_NAME_INFO,
4358                                4, CLI_BUFFER_SIZE, &recv_flags2,
4359                                &rdata, &num_rdata);
4360         if (!NT_STATUS_IS_OK(status)) {
4361                 return status;
4362         }
4363
4364         namelen = IVAL(rdata, 0);
4365         if (namelen > (num_rdata - 4)) {
4366                 TALLOC_FREE(rdata);
4367                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4368         }
4369
4370         pull_string_talloc(mem_ctx,
4371                            (const char *)rdata,
4372                            recv_flags2,
4373                            &name,
4374                            rdata + 4,
4375                            namelen,
4376                            STR_UNICODE);
4377         if (name == NULL) {
4378                 status = map_nt_error_from_unix(errno);
4379                 TALLOC_FREE(rdata);
4380                 return status;
4381         }
4382
4383         *_name = name;
4384         TALLOC_FREE(rdata);
4385         return NT_STATUS_OK;
4386 }
4387
4388 /*
4389   This checks a couple of trans2 calls
4390 */
4391 static bool run_trans2test(int dummy)
4392 {
4393         struct cli_state *cli;
4394         uint16_t fnum;
4395         off_t size;
4396         time_t c_time, a_time, m_time;
4397         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4398         const char *fname = "\\trans2.tst";
4399         const char *dname = "\\trans2";
4400         const char *fname2 = "\\trans2\\trans2.tst";
4401         char *pname = NULL;
4402         bool correct = True;
4403         NTSTATUS status;
4404         uint32_t fs_attr;
4405         uint64_t ino;
4406
4407         printf("starting trans2 test\n");
4408
4409         if (!torture_open_connection(&cli, 0)) {
4410                 return False;
4411         }
4412
4413         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4414                 /* Ensure ino is zero, SMB2 gets a real one. */
4415                 ino = 0;
4416         } else {
4417                 /* Ensure ino is -1, SMB1 never gets a real one. */
4418                 ino = (uint64_t)-1;
4419         }
4420
4421         status = cli_get_fs_attr_info(cli, &fs_attr);
4422         if (!NT_STATUS_IS_OK(status)) {
4423                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4424                        nt_errstr(status));
4425                 correct = false;
4426         }
4427
4428         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4429         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4430         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4431                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4432         if (!NT_STATUS_IS_OK(status)) {
4433                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4434                 correct = False;
4435         }
4436
4437         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4438         if (!NT_STATUS_IS_OK(status)) {
4439                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4440                 correct = False;
4441         }
4442         else if (strcmp(pname, fname)) {
4443                 printf("qfilename gave different name? [%s] [%s]\n",
4444                        fname, pname);
4445                 correct = False;
4446         }
4447
4448         cli_close(cli, fnum);
4449
4450         sleep(2);
4451
4452         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4453         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4454                           &fnum);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4457                 return False;
4458         }
4459         cli_close(cli, fnum);
4460
4461         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4462                                 NULL);
4463         if (!NT_STATUS_IS_OK(status)) {
4464                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4465                 correct = False;
4466         } else {
4467                 time_t t = time(NULL);
4468
4469                 if (c_time != m_time) {
4470                         printf("create time=%s", ctime(&c_time));
4471                         printf("modify time=%s", ctime(&m_time));
4472                         printf("This system appears to have sticky create times\n");
4473                 }
4474                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4475                         printf("access time=%s", ctime(&a_time));
4476                         printf("This system appears to set a midnight access time\n");
4477                         correct = False;
4478                 }
4479
4480                 if (labs(m_time - t) > 60*60*24*7) {
4481                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4482                         correct = False;
4483                 }
4484         }
4485
4486
4487         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4488         cli_openx(cli, fname, 
4489                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4490         cli_close(cli, fnum);
4491         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4492                                 &m_time_ts, &size, NULL, &ino);
4493         if (!NT_STATUS_IS_OK(status)) {
4494                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4495                 correct = False;
4496         } else {
4497                 if (w_time_ts.tv_sec < 60*60*24*2) {
4498                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4499                         printf("This system appears to set a initial 0 write time\n");
4500                         correct = False;
4501                 }
4502                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4503                         /* SMB2 should always return an inode. */
4504                         if (ino == 0) {
4505                                 printf("SMB2 bad inode (0)\n");
4506                                 correct = false;
4507                         }
4508                 } else {
4509                         /* SMB1 must always return zero here. */
4510                         if (ino != 0) {
4511                                 printf("SMB1 bad inode (!0)\n");
4512                                 correct = false;
4513                         }
4514                 }
4515         }
4516
4517         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4518
4519
4520         /* check if the server updates the directory modification time
4521            when creating a new file */
4522         status = cli_mkdir(cli, dname);
4523         if (!NT_STATUS_IS_OK(status)) {
4524                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4525                 correct = False;
4526         }
4527         sleep(3);
4528         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4529                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4530         if (!NT_STATUS_IS_OK(status)) {
4531                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4532                 correct = False;
4533         }
4534
4535         cli_openx(cli, fname2, 
4536                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4537         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4538         cli_close(cli, fnum);
4539         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4540                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4541         if (!NT_STATUS_IS_OK(status)) {
4542                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4543                 correct = False;
4544         } else {
4545                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4546                     == 0) {
4547                         printf("This system does not update directory modification times\n");
4548                         correct = False;
4549                 }
4550         }
4551         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4552         cli_rmdir(cli, dname);
4553
4554         if (!torture_close_connection(cli)) {
4555                 correct = False;
4556         }
4557
4558         printf("trans2 test finished\n");
4559
4560         return correct;
4561 }
4562
4563 /*
4564   This checks new W2K calls.
4565 */
4566
4567 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4568 {
4569         uint8_t *buf = NULL;
4570         uint32_t len;
4571         NTSTATUS status;
4572
4573         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4574                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4575         if (!NT_STATUS_IS_OK(status)) {
4576                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4577                        nt_errstr(status));
4578         } else {
4579                 printf("qfileinfo: level %d, len = %u\n", level, len);
4580                 dump_data(0, (uint8_t *)buf, len);
4581                 printf("\n");
4582         }
4583         TALLOC_FREE(buf);
4584         return status;
4585 }
4586
4587 static bool run_w2ktest(int dummy)
4588 {
4589         struct cli_state *cli;
4590         uint16_t fnum;
4591         const char *fname = "\\w2ktest\\w2k.tst";
4592         int level;
4593         bool correct = True;
4594
4595         printf("starting w2k test\n");
4596
4597         if (!torture_open_connection(&cli, 0)) {
4598                 return False;
4599         }
4600
4601         cli_openx(cli, fname, 
4602                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4603
4604         for (level = 1004; level < 1040; level++) {
4605                 new_trans(cli, fnum, level);
4606         }
4607
4608         cli_close(cli, fnum);
4609
4610         if (!torture_close_connection(cli)) {
4611                 correct = False;
4612         }
4613
4614         printf("w2k test finished\n");
4615
4616         return correct;
4617 }
4618
4619
4620 /*
4621   this is a harness for some oplock tests
4622  */
4623 static bool run_oplock1(int dummy)
4624 {
4625         struct cli_state *cli1;
4626         const char *fname = "\\lockt1.lck";
4627         uint16_t fnum1;
4628         bool correct = True;
4629         NTSTATUS status;
4630
4631         printf("starting oplock test 1\n");
4632
4633         if (!torture_open_connection(&cli1, 0)) {
4634                 return False;
4635         }
4636
4637         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4638
4639         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4640
4641         cli1->use_oplocks = True;
4642
4643         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4644                           &fnum1);
4645         if (!NT_STATUS_IS_OK(status)) {
4646                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4647                 return False;
4648         }
4649
4650         cli1->use_oplocks = False;
4651
4652         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4653         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4654
4655         status = cli_close(cli1, fnum1);
4656         if (!NT_STATUS_IS_OK(status)) {
4657                 printf("close2 failed (%s)\n", nt_errstr(status));
4658                 return False;
4659         }
4660
4661         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4662         if (!NT_STATUS_IS_OK(status)) {
4663                 printf("unlink failed (%s)\n", nt_errstr(status));
4664                 return False;
4665         }
4666
4667         if (!torture_close_connection(cli1)) {
4668                 correct = False;
4669         }
4670
4671         printf("finished oplock test 1\n");
4672
4673         return correct;
4674 }
4675
4676 static bool run_oplock2(int dummy)
4677 {
4678         struct cli_state *cli1, *cli2;
4679         const char *fname = "\\lockt2.lck";
4680         uint16_t fnum1, fnum2;
4681         int saved_use_oplocks = use_oplocks;
4682         char buf[4];
4683         bool correct = True;
4684         volatile bool *shared_correct;
4685         size_t nread;
4686         NTSTATUS status;
4687
4688         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4689         *shared_correct = True;
4690
4691         use_level_II_oplocks = True;
4692         use_oplocks = True;
4693
4694         printf("starting oplock test 2\n");
4695
4696         if (!torture_open_connection(&cli1, 0)) {
4697                 use_level_II_oplocks = False;
4698                 use_oplocks = saved_use_oplocks;
4699                 return False;
4700         }
4701
4702         if (!torture_open_connection(&cli2, 1)) {
4703                 use_level_II_oplocks = False;
4704                 use_oplocks = saved_use_oplocks;
4705                 return False;
4706         }
4707
4708         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4709
4710         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4711         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4712
4713         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4714                           &fnum1);
4715         if (!NT_STATUS_IS_OK(status)) {
4716                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4717                 return False;
4718         }
4719
4720         /* Don't need the globals any more. */
4721         use_level_II_oplocks = False;
4722         use_oplocks = saved_use_oplocks;
4723
4724         if (fork() == 0) {
4725                 /* Child code */
4726                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4727                 if (!NT_STATUS_IS_OK(status)) {
4728                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4729                         *shared_correct = False;
4730                         exit(0);
4731                 }
4732
4733                 sleep(2);
4734
4735                 status = cli_close(cli2, fnum2);
4736                 if (!NT_STATUS_IS_OK(status)) {
4737                         printf("close2 failed (%s)\n", nt_errstr(status));
4738                         *shared_correct = False;
4739                 }
4740
4741                 exit(0);
4742         }
4743
4744         sleep(2);
4745
4746         /* Ensure cli1 processes the break. Empty file should always return 0
4747          * bytes.  */
4748         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4749         if (!NT_STATUS_IS_OK(status)) {
4750                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4751                 correct = false;
4752         } else if (nread != 0) {
4753                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4754                       (unsigned long)nread, 0);
4755                 correct = false;
4756         }
4757
4758         /* Should now be at level II. */
4759         /* Test if sending a write locks causes a break to none. */
4760         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4761         if (!NT_STATUS_IS_OK(status)) {
4762                 printf("lock failed (%s)\n", nt_errstr(status));
4763                 correct = False;
4764         }
4765
4766         cli_unlock(cli1, fnum1, 0, 4);
4767
4768         sleep(2);
4769
4770         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4771         if (!NT_STATUS_IS_OK(status)) {
4772                 printf("lock failed (%s)\n", nt_errstr(status));
4773                 correct = False;
4774         }
4775
4776         cli_unlock(cli1, fnum1, 0, 4);
4777
4778         sleep(2);
4779
4780         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4781
4782         status = cli_close(cli1, fnum1);
4783         if (!NT_STATUS_IS_OK(status)) {
4784                 printf("close1 failed (%s)\n", nt_errstr(status));
4785                 correct = False;
4786         }
4787
4788         sleep(4);
4789
4790         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4791         if (!NT_STATUS_IS_OK(status)) {
4792                 printf("unlink failed (%s)\n", nt_errstr(status));
4793                 correct = False;
4794         }
4795
4796         if (!torture_close_connection(cli1)) {
4797                 correct = False;
4798         }
4799
4800         if (!*shared_correct) {
4801                 correct = False;
4802         }
4803
4804         printf("finished oplock test 2\n");
4805
4806         return correct;
4807 }
4808
4809 struct oplock4_state {
4810         struct tevent_context *ev;
4811         struct cli_state *cli;
4812         bool *got_break;
4813         uint16_t *fnum2;
4814 };
4815
4816 static void oplock4_got_break(struct tevent_req *req);
4817 static void oplock4_got_open(struct tevent_req *req);
4818
4819 static bool run_oplock4(int dummy)
4820 {
4821         struct tevent_context *ev;
4822         struct cli_state *cli1, *cli2;
4823         struct tevent_req *oplock_req, *open_req;
4824         const char *fname = "\\lockt4.lck";
4825         const char *fname_ln = "\\lockt4_ln.lck";
4826         uint16_t fnum1, fnum2;
4827         int saved_use_oplocks = use_oplocks;
4828         NTSTATUS status;
4829         bool correct = true;
4830
4831         bool got_break;
4832
4833         struct oplock4_state *state;
4834
4835         printf("starting oplock test 4\n");
4836
4837         if (!torture_open_connection(&cli1, 0)) {
4838                 use_level_II_oplocks = false;
4839                 use_oplocks = saved_use_oplocks;
4840                 return false;
4841         }
4842
4843         if (!torture_open_connection(&cli2, 1)) {
4844                 use_level_II_oplocks = false;
4845                 use_oplocks = saved_use_oplocks;
4846                 return false;
4847         }
4848
4849         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4850         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4851
4852         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4853         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4854
4855         /* Create the file. */
4856         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4857                           &fnum1);
4858         if (!NT_STATUS_IS_OK(status)) {
4859                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4860                 return false;
4861         }
4862
4863         status = cli_close(cli1, fnum1);
4864         if (!NT_STATUS_IS_OK(status)) {
4865                 printf("close1 failed (%s)\n", nt_errstr(status));
4866                 return false;
4867         }
4868
4869         /* Now create a hardlink. */
4870         status = cli_hardlink(cli1, fname, fname_ln);
4871         if (!NT_STATUS_IS_OK(status)) {
4872                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4873                 return false;
4874         }
4875
4876         /* Prove that opening hardlinks cause deny modes to conflict. */
4877         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4878         if (!NT_STATUS_IS_OK(status)) {
4879                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4880                 return false;
4881         }
4882
4883         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4884         if (NT_STATUS_IS_OK(status)) {
4885                 printf("open of %s succeeded - should fail with sharing violation.\n",
4886                         fname_ln);
4887                 return false;
4888         }
4889
4890         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4891                 printf("open of %s should fail with sharing violation. Got %s\n",
4892                         fname_ln, nt_errstr(status));
4893                 return false;
4894         }
4895
4896         status = cli_close(cli1, fnum1);
4897         if (!NT_STATUS_IS_OK(status)) {
4898                 printf("close1 failed (%s)\n", nt_errstr(status));
4899                 return false;
4900         }
4901
4902         cli1->use_oplocks = true;
4903         cli2->use_oplocks = true;
4904
4905         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4906         if (!NT_STATUS_IS_OK(status)) {
4907                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4908                 return false;
4909         }
4910
4911         ev = samba_tevent_context_init(talloc_tos());
4912         if (ev == NULL) {
4913                 printf("tevent_context_init failed\n");
4914                 return false;
4915         }
4916
4917         state = talloc(ev, struct oplock4_state);
4918         if (state == NULL) {
4919                 printf("talloc failed\n");
4920                 return false;
4921         }
4922         state->ev = ev;
4923         state->cli = cli1;
4924         state->got_break = &got_break;
4925         state->fnum2 = &fnum2;
4926
4927         oplock_req = cli_smb_oplock_break_waiter_send(
4928                 talloc_tos(), ev, cli1);
4929         if (oplock_req == NULL) {
4930                 printf("cli_smb_oplock_break_waiter_send failed\n");
4931                 return false;
4932         }
4933         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4934
4935         open_req = cli_openx_send(
4936                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4937         if (open_req == NULL) {
4938                 printf("cli_openx_send failed\n");
4939                 return false;
4940         }
4941         tevent_req_set_callback(open_req, oplock4_got_open, state);
4942
4943         got_break = false;
4944         fnum2 = 0xffff;
4945
4946         while (!got_break || fnum2 == 0xffff) {
4947                 int ret;
4948                 ret = tevent_loop_once(ev);
4949                 if (ret == -1) {
4950                         printf("tevent_loop_once failed: %s\n",
4951                                strerror(errno));
4952                         return false;
4953                 }
4954         }
4955
4956         status = cli_close(cli2, fnum2);
4957         if (!NT_STATUS_IS_OK(status)) {
4958                 printf("close2 failed (%s)\n", nt_errstr(status));
4959                 correct = false;
4960         }
4961
4962         status = cli_close(cli1, fnum1);
4963         if (!NT_STATUS_IS_OK(status)) {
4964                 printf("close1 failed (%s)\n", nt_errstr(status));
4965                 correct = false;
4966         }
4967
4968         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4969         if (!NT_STATUS_IS_OK(status)) {
4970                 printf("unlink failed (%s)\n", nt_errstr(status));
4971                 correct = false;
4972         }
4973
4974         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4975         if (!NT_STATUS_IS_OK(status)) {
4976                 printf("unlink failed (%s)\n", nt_errstr(status));
4977                 correct = false;
4978         }
4979
4980         if (!torture_close_connection(cli1)) {
4981                 correct = false;
4982         }
4983
4984         if (!got_break) {
4985                 correct = false;
4986         }
4987
4988         printf("finished oplock test 4\n");
4989
4990         return correct;
4991 }
4992
4993 static void oplock4_got_break(struct tevent_req *req)
4994 {
4995         struct oplock4_state *state = tevent_req_callback_data(
4996                 req, struct oplock4_state);
4997         uint16_t fnum;
4998         uint8_t level;
4999         NTSTATUS status;
5000
5001         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5002         TALLOC_FREE(req);
5003         if (!NT_STATUS_IS_OK(status)) {
5004                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5005                        nt_errstr(status));
5006                 return;
5007         }
5008         *state->got_break = true;
5009
5010         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5011                                   NO_OPLOCK);
5012         if (req == NULL) {
5013                 printf("cli_oplock_ack_send failed\n");
5014                 return;
5015         }
5016 }
5017
5018 static void oplock4_got_open(struct tevent_req *req)
5019 {
5020         struct oplock4_state *state = tevent_req_callback_data(
5021                 req, struct oplock4_state);
5022         NTSTATUS status;
5023
5024         status = cli_openx_recv(req, state->fnum2);
5025         if (!NT_STATUS_IS_OK(status)) {
5026                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5027                 *state->fnum2 = 0xffff;
5028         }
5029 }
5030
5031 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5032
5033 struct oplock5_state {
5034         int pipe_down_fd;
5035 };
5036
5037 /*
5038  * Async open the file that has a kernel oplock, do an echo to get
5039  * that 100% across, close the file to signal to the child fd that the
5040  * oplock can be dropped, wait for the open reply.
5041  */
5042
5043 static void oplock5_opened(struct tevent_req *subreq);
5044 static void oplock5_pong(struct tevent_req *subreq);
5045 static void oplock5_timedout(struct tevent_req *subreq);
5046
5047 static struct tevent_req *oplock5_send(
5048         TALLOC_CTX *mem_ctx,
5049         struct tevent_context *ev,
5050         struct cli_state *cli,
5051         const char *fname,
5052         int pipe_down_fd)
5053 {
5054         struct tevent_req *req = NULL, *subreq = NULL;
5055         struct oplock5_state *state = NULL;
5056         static uint8_t data = 0;
5057
5058         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5059         if (req == NULL) {
5060                 return NULL;
5061         }
5062         state->pipe_down_fd = pipe_down_fd;
5063
5064         subreq = cli_ntcreate_send(
5065                 state,
5066                 ev,
5067                 cli,
5068                 fname,
5069                 0,                      /* CreatFlags */
5070                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5071                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5072                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5073                 FILE_OPEN,               /* CreateDisposition */
5074                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5075                 0,                       /* Impersonation */
5076                 0);                      /* SecurityFlags */
5077         if (tevent_req_nomem(subreq, req)) {
5078                 return tevent_req_post(req, ev);
5079         }
5080         tevent_req_set_callback(subreq, oplock5_opened, req);
5081
5082         subreq = cli_echo_send(
5083                 state,
5084                 ev,
5085                 cli,
5086                 1,
5087                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5088         if (tevent_req_nomem(subreq, req)) {
5089                 return tevent_req_post(req, ev);
5090         }
5091         tevent_req_set_callback(subreq, oplock5_pong, req);
5092
5093         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5094         if (tevent_req_nomem(subreq, req)) {
5095                 return tevent_req_post(req, ev);
5096         }
5097         tevent_req_set_callback(subreq, oplock5_timedout, req);
5098
5099         return req;
5100 }
5101
5102 static void oplock5_opened(struct tevent_req *subreq)
5103 {
5104         struct tevent_req *req = tevent_req_callback_data(
5105                 subreq, struct tevent_req);
5106         NTSTATUS status;
5107         uint16_t fnum;
5108
5109         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5110         TALLOC_FREE(subreq);
5111         if (tevent_req_nterror(req, status)) {
5112                 return;
5113         }
5114         tevent_req_done(req);
5115 }
5116
5117 static void oplock5_pong(struct tevent_req *subreq)
5118 {
5119         struct tevent_req *req = tevent_req_callback_data(
5120                 subreq, struct tevent_req);
5121         struct oplock5_state *state = tevent_req_data(
5122                 req, struct oplock5_state);
5123         NTSTATUS status;
5124
5125         status = cli_echo_recv(subreq);
5126         TALLOC_FREE(subreq);
5127         if (tevent_req_nterror(req, status)) {
5128                 return;
5129         }
5130
5131         close(state->pipe_down_fd);
5132 }
5133
5134 static void oplock5_timedout(struct tevent_req *subreq)
5135 {
5136         struct tevent_req *req = tevent_req_callback_data(
5137                 subreq, struct tevent_req);
5138         bool ok;
5139
5140         ok = tevent_wakeup_recv(subreq);
5141         TALLOC_FREE(subreq);
5142         if (!ok) {
5143                 tevent_req_oom(req);
5144                 return;
5145         }
5146         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5147 }
5148
5149 static NTSTATUS oplock5_recv(struct tevent_req *req)
5150 {
5151         return tevent_req_simple_recv_ntstatus(req);
5152 }
5153
5154 static bool run_oplock5(int dummy)
5155 {
5156         struct tevent_context *ev = NULL;
5157         struct tevent_req *req = NULL;
5158         struct cli_state *cli = NULL;
5159         const char *fname = "oplock5.txt";
5160         int pipe_down[2], pipe_up[2];
5161         pid_t child_pid;
5162         uint8_t c = '\0';
5163         NTSTATUS status;
5164         int ret;
5165         bool ok;
5166
5167         printf("starting oplock5\n");
5168
5169         if (local_path == NULL) {
5170                 d_fprintf(stderr, "oplock5 must be given a local path via "
5171                           "-l <localpath>\n");
5172                 return false;
5173         }
5174
5175         ret = pipe(pipe_down);
5176         if (ret == -1) {
5177                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5178                 return false;
5179         }
5180         ret = pipe(pipe_up);
5181         if (ret == -1) {
5182                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5183                 return false;
5184         }
5185
5186         child_pid = fork();
5187         if (child_pid == -1) {
5188                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5189                 return false;
5190         }
5191
5192         if (child_pid == 0) {
5193                 char *local_file = NULL;
5194                 int fd;
5195
5196                 close(pipe_down[1]);
5197                 close(pipe_up[0]);
5198
5199                 local_file = talloc_asprintf(
5200                         talloc_tos(), "%s/%s", local_path, fname);
5201                 if (local_file == 0) {
5202                         c = 1;
5203                         goto do_write;
5204                 }
5205                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5206                 if (fd == -1) {
5207                         d_fprintf(stderr,
5208                                   "open(%s) in child failed: %s\n",
5209                                   local_file,
5210                                   strerror(errno));
5211                         c = 2;
5212                         goto do_write;
5213                 }
5214
5215                 signal(SIGIO, SIG_IGN);
5216
5217                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5218                 if (ret == -1) {
5219                         d_fprintf(stderr,
5220                                   "SETLEASE in child failed: %s\n",
5221                                   strerror(errno));
5222                         c = 3;
5223                         goto do_write;
5224                 }
5225
5226         do_write:
5227                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5228                 if (ret == -1) {
5229                         d_fprintf(stderr,
5230                                   "sys_write failed: %s\n",
5231                                   strerror(errno));
5232                         exit(4);
5233                 }
5234                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5235                 if (ret == -1) {
5236                         d_fprintf(stderr,
5237                                   "sys_read failed: %s\n",
5238                                   strerror(errno));
5239                         exit(5);
5240                 }
5241                 exit(0);
5242         }
5243
5244         close(pipe_up[1]);
5245         close(pipe_down[0]);
5246
5247         ret = sys_read(pipe_up[0], &c, sizeof(c));
5248         if (ret != 1) {
5249                 d_fprintf(stderr,
5250                           "sys_read failed: %s\n",
5251                           strerror(errno));
5252                 return false;
5253         }
5254         if (c != 0) {
5255                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5256                 return false;
5257         }
5258
5259         ok = torture_open_connection(&cli, 0);
5260         if (!ok) {
5261                 d_fprintf(stderr, "torture_open_connection failed\n");
5262                 return false;
5263         }
5264
5265         ev = samba_tevent_context_init(talloc_tos());
5266         if (ev == NULL) {
5267                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5268                 return false;
5269         }
5270
5271         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5272         if (req == NULL) {
5273                 d_fprintf(stderr, "oplock5_send failed\n");
5274                 return false;
5275         }
5276
5277         ok = tevent_req_poll_ntstatus(req, ev, &status);
5278         if (!ok) {
5279                 d_fprintf(stderr,
5280                           "tevent_req_poll_ntstatus failed: %s\n",
5281                           nt_errstr(status));
5282                 return false;
5283         }
5284
5285         status = oplock5_recv(req);
5286         TALLOC_FREE(req);
5287         if (!NT_STATUS_IS_OK(status)) {
5288                 d_fprintf(stderr,
5289                           "oplock5 failed: %s\n",
5290                           nt_errstr(status));
5291                 return false;
5292         }
5293
5294         return true;
5295 }
5296
5297 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5298
5299 /*
5300   Test delete on close semantics.
5301  */
5302 static bool run_deletetest(int dummy)
5303 {
5304         struct cli_state *cli1 = NULL;
5305         struct cli_state *cli2 = NULL;
5306         const char *fname = "\\delete.file";
5307         uint16_t fnum1 = (uint16_t)-1;
5308         uint16_t fnum2 = (uint16_t)-1;
5309         bool correct = false;
5310         NTSTATUS status;
5311
5312         printf("starting delete test\n");
5313
5314         if (!torture_open_connection(&cli1, 0)) {
5315                 return False;
5316         }
5317
5318         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5319
5320         /* Test 1 - this should delete the file on close. */
5321
5322         cli_setatr(cli1, fname, 0, 0);
5323         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5324
5325         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5326                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5327                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5328         if (!NT_STATUS_IS_OK(status)) {
5329                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5330                 goto fail;
5331         }
5332
5333         status = cli_close(cli1, fnum1);
5334         if (!NT_STATUS_IS_OK(status)) {
5335                 printf("[1] close failed (%s)\n", nt_errstr(status));
5336                 goto fail;
5337         }
5338
5339         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5340         if (NT_STATUS_IS_OK(status)) {
5341                 printf("[1] open of %s succeeded (should fail)\n", fname);
5342                 goto fail;
5343         }
5344
5345         printf("first delete on close test succeeded.\n");
5346
5347         /* Test 2 - this should delete the file on close. */
5348
5349         cli_setatr(cli1, fname, 0, 0);
5350         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5351
5352         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5353                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5354                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5355         if (!NT_STATUS_IS_OK(status)) {
5356                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5357                 goto fail;
5358         }
5359
5360         status = cli_nt_delete_on_close(cli1, fnum1, true);
5361         if (!NT_STATUS_IS_OK(status)) {
5362                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5363                 goto fail;
5364         }
5365
5366         status = cli_close(cli1, fnum1);
5367         if (!NT_STATUS_IS_OK(status)) {
5368                 printf("[2] close failed (%s)\n", nt_errstr(status));
5369                 goto fail;
5370         }
5371
5372         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5373         if (NT_STATUS_IS_OK(status)) {
5374                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5375                 status = cli_close(cli1, fnum1);
5376                 if (!NT_STATUS_IS_OK(status)) {
5377                         printf("[2] close failed (%s)\n", nt_errstr(status));
5378                 }
5379                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5380                 goto fail;
5381         }
5382
5383         printf("second delete on close test succeeded.\n");
5384
5385         /* Test 3 - ... */
5386         cli_setatr(cli1, fname, 0, 0);
5387         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5388
5389         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5390                               FILE_ATTRIBUTE_NORMAL,
5391                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5392                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5393         if (!NT_STATUS_IS_OK(status)) {
5394                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5395                 goto fail;
5396         }
5397
5398         /* This should fail with a sharing violation - open for delete is only compatible
5399            with SHARE_DELETE. */
5400
5401         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5402                               FILE_ATTRIBUTE_NORMAL,
5403                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5404                               FILE_OPEN, 0, 0, &fnum2, NULL);
5405         if (NT_STATUS_IS_OK(status)) {
5406                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5407                 goto fail;
5408         }
5409
5410         /* This should succeed. */
5411         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5412                              FILE_ATTRIBUTE_NORMAL,
5413                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5414                              FILE_OPEN, 0, 0, &fnum2, NULL);
5415         if (!NT_STATUS_IS_OK(status)) {
5416                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5417                 goto fail;
5418         }
5419
5420         status = cli_nt_delete_on_close(cli1, fnum1, true);
5421         if (!NT_STATUS_IS_OK(status)) {
5422                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5423                 goto fail;
5424         }
5425
5426         status = cli_close(cli1, fnum1);
5427         if (!NT_STATUS_IS_OK(status)) {
5428                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5429                 goto fail;
5430         }
5431
5432         status = cli_close(cli1, fnum2);
5433         if (!NT_STATUS_IS_OK(status)) {
5434                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5435                 goto fail;
5436         }
5437
5438         /* This should fail - file should no longer be there. */
5439
5440         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5441         if (NT_STATUS_IS_OK(status)) {
5442                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5443                 status = cli_close(cli1, fnum1);
5444                 if (!NT_STATUS_IS_OK(status)) {
5445                         printf("[3] close failed (%s)\n", nt_errstr(status));
5446                 }
5447                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5448                 goto fail;
5449         }
5450
5451         printf("third delete on close test succeeded.\n");
5452
5453         /* Test 4 ... */
5454         cli_setatr(cli1, fname, 0, 0);
5455         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5456
5457         status = cli_ntcreate(cli1, fname, 0,
5458                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5459                               FILE_ATTRIBUTE_NORMAL,
5460                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5461                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5462         if (!NT_STATUS_IS_OK(status)) {
5463                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5464                 goto fail;
5465         }
5466
5467         /* This should succeed. */
5468         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5469                              FILE_ATTRIBUTE_NORMAL,
5470                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5471                              FILE_OPEN, 0, 0, &fnum2, NULL);
5472         if (!NT_STATUS_IS_OK(status)) {
5473                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5474                 goto fail;
5475         }
5476
5477         status = cli_close(cli1, fnum2);
5478         if (!NT_STATUS_IS_OK(status)) {
5479                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5480                 goto fail;
5481         }
5482
5483         status = cli_nt_delete_on_close(cli1, fnum1, true);
5484         if (!NT_STATUS_IS_OK(status)) {
5485                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5486                 goto fail;
5487         }
5488
5489         /* This should fail - no more opens once delete on close set. */
5490         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5491                               FILE_ATTRIBUTE_NORMAL,
5492                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5493                               FILE_OPEN, 0, 0, &fnum2, NULL);
5494         if (NT_STATUS_IS_OK(status)) {
5495                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5496                 goto fail;
5497         }
5498
5499         status = cli_close(cli1, fnum1);
5500         if (!NT_STATUS_IS_OK(status)) {
5501                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5502                 goto fail;
5503         }
5504
5505         printf("fourth delete on close test succeeded.\n");
5506
5507         /* Test 5 ... */
5508         cli_setatr(cli1, fname, 0, 0);
5509         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5510
5511         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5512         if (!NT_STATUS_IS_OK(status)) {
5513                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5514                 goto fail;
5515         }
5516
5517         /* This should fail - only allowed on NT opens with DELETE access. */
5518
5519         status = cli_nt_delete_on_close(cli1, fnum1, true);
5520         if (NT_STATUS_IS_OK(status)) {
5521                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5522                 goto fail;
5523         }
5524
5525         status = cli_close(cli1, fnum1);
5526         if (!NT_STATUS_IS_OK(status)) {
5527                 printf("[5] close failed (%s)\n", nt_errstr(status));
5528                 goto fail;
5529         }
5530
5531         printf("fifth delete on close test succeeded.\n");
5532
5533         /* Test 6 ... */
5534         cli_setatr(cli1, fname, 0, 0);
5535         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5536
5537         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5538                              FILE_ATTRIBUTE_NORMAL,
5539                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5540                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5541         if (!NT_STATUS_IS_OK(status)) {
5542                 printf("[6] open of %s failed (%s)\n", fname,
5543                        nt_errstr(status));
5544                 goto fail;
5545         }
5546
5547         /* This should fail - only allowed on NT opens with DELETE access. */
5548
5549         status = cli_nt_delete_on_close(cli1, fnum1, true);
5550         if (NT_STATUS_IS_OK(status)) {
5551                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5552                 goto fail;
5553         }
5554
5555         status = cli_close(cli1, fnum1);
5556         if (!NT_STATUS_IS_OK(status)) {
5557                 printf("[6] close failed (%s)\n", nt_errstr(status));
5558                 goto fail;
5559         }
5560
5561         printf("sixth delete on close test succeeded.\n");
5562
5563         /* Test 7 ... */
5564         cli_setatr(cli1, fname, 0, 0);
5565         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5566
5567         status = cli_ntcreate(cli1, fname, 0,
5568                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5569                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5570                               0, 0, &fnum1, NULL);
5571         if (!NT_STATUS_IS_OK(status)) {
5572                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5573                 goto fail;
5574         }
5575
5576         status = cli_nt_delete_on_close(cli1, fnum1, true);
5577         if (!NT_STATUS_IS_OK(status)) {
5578                 printf("[7] setting delete_on_close on file failed !\n");
5579                 goto fail;
5580         }
5581
5582         status = cli_nt_delete_on_close(cli1, fnum1, false);
5583         if (!NT_STATUS_IS_OK(status)) {
5584                 printf("[7] unsetting delete_on_close on file failed !\n");
5585                 goto fail;
5586         }
5587
5588         status = cli_close(cli1, fnum1);
5589         if (!NT_STATUS_IS_OK(status)) {
5590                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5591                 goto fail;
5592         }
5593
5594         /* This next open should succeed - we reset the flag. */
5595         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5596         if (!NT_STATUS_IS_OK(status)) {
5597                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5598                 goto fail;
5599         }
5600
5601         status = cli_close(cli1, fnum1);
5602         if (!NT_STATUS_IS_OK(status)) {
5603                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5604                 goto fail;
5605         }
5606
5607         printf("seventh delete on close test succeeded.\n");
5608
5609         /* Test 8 ... */
5610         cli_setatr(cli1, fname, 0, 0);
5611         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5612
5613         if (!torture_open_connection(&cli2, 1)) {
5614                 printf("[8] failed to open second connection.\n");
5615                 goto fail;
5616         }
5617
5618         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5619
5620         status = cli_ntcreate(cli1, fname, 0,
5621                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5622                              FILE_ATTRIBUTE_NORMAL,
5623                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5624                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5625         if (!NT_STATUS_IS_OK(status)) {
5626                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5627                 goto fail;
5628         }
5629
5630         status = cli_ntcreate(cli2, fname, 0,
5631                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5632                              FILE_ATTRIBUTE_NORMAL,
5633                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5634                              FILE_OPEN, 0, 0, &fnum2, NULL);
5635         if (!NT_STATUS_IS_OK(status)) {
5636                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5637                 goto fail;
5638         }
5639
5640         status = cli_nt_delete_on_close(cli1, fnum1, true);
5641         if (!NT_STATUS_IS_OK(status)) {
5642                 printf("[8] setting delete_on_close on file failed !\n");
5643                 goto fail;
5644         }
5645
5646         status = cli_close(cli1, fnum1);
5647         if (!NT_STATUS_IS_OK(status)) {
5648                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5649                 goto fail;
5650         }
5651
5652         status = cli_close(cli2, fnum2);
5653         if (!NT_STATUS_IS_OK(status)) {
5654                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5655                 goto fail;
5656         }
5657
5658         /* This should fail.. */
5659         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5660         if (NT_STATUS_IS_OK(status)) {
5661                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5662                 goto fail;
5663         }
5664
5665         printf("eighth delete on close test succeeded.\n");
5666
5667         /* Test 9 ... */
5668
5669         /* This should fail - we need to set DELETE_ACCESS. */
5670         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5671                               FILE_ATTRIBUTE_NORMAL,
5672                               FILE_SHARE_NONE,
5673                               FILE_OVERWRITE_IF,
5674                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5675         if (NT_STATUS_IS_OK(status)) {
5676                 printf("[9] open of %s succeeded should have failed!\n", fname);
5677                 goto fail;
5678         }
5679
5680         printf("ninth delete on close test succeeded.\n");
5681
5682         /* Test 10 ... */
5683
5684         status = cli_ntcreate(cli1, fname, 0,
5685                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5686                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5687                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5688                              0, &fnum1, NULL);
5689         if (!NT_STATUS_IS_OK(status)) {
5690                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5691                 goto fail;
5692         }
5693
5694         /* This should delete the file. */
5695         status = cli_close(cli1, fnum1);
5696         if (!NT_STATUS_IS_OK(status)) {
5697                 printf("[10] close failed (%s)\n", nt_errstr(status));
5698                 goto fail;
5699         }
5700
5701         /* This should fail.. */
5702         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5703         if (NT_STATUS_IS_OK(status)) {
5704                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5705                 goto fail;
5706         }
5707
5708         printf("tenth delete on close test succeeded.\n");
5709
5710         /* Test 11 ... */
5711
5712         cli_setatr(cli1, fname, 0, 0);
5713         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5714
5715         /* Can we open a read-only file with delete access? */
5716
5717         /* Create a readonly file. */
5718         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5719                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5720                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5721         if (!NT_STATUS_IS_OK(status)) {
5722                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5723                 goto fail;
5724         }
5725
5726         status = cli_close(cli1, fnum1);
5727         if (!NT_STATUS_IS_OK(status)) {
5728                 printf("[11] close failed (%s)\n", nt_errstr(status));
5729                 goto fail;
5730         }
5731
5732         /* Now try open for delete access. */
5733         status = cli_ntcreate(cli1, fname, 0,
5734                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5735                              0,
5736                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5737                              FILE_OPEN, 0, 0, &fnum1, NULL);
5738         if (!NT_STATUS_IS_OK(status)) {
5739                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5740                 goto fail;
5741         }
5742
5743         cli_close(cli1, fnum1);
5744
5745         printf("eleventh delete on close test succeeded.\n");
5746
5747         /*
5748          * Test 12
5749          * like test 4 but with initial delete on close
5750          */
5751
5752         cli_setatr(cli1, fname, 0, 0);
5753         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5754
5755         status = cli_ntcreate(cli1, fname, 0,
5756                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5757                               FILE_ATTRIBUTE_NORMAL,
5758                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5759                               FILE_OVERWRITE_IF,
5760                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5761         if (!NT_STATUS_IS_OK(status)) {
5762                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5763                 goto fail;
5764         }
5765
5766         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5767                               FILE_ATTRIBUTE_NORMAL,
5768                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5769                               FILE_OPEN, 0, 0, &fnum2, NULL);
5770         if (!NT_STATUS_IS_OK(status)) {
5771                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5772                 goto fail;
5773         }
5774
5775         status = cli_close(cli1, fnum2);
5776         if (!NT_STATUS_IS_OK(status)) {
5777                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5778                 goto fail;
5779         }
5780
5781         status = cli_nt_delete_on_close(cli1, fnum1, true);
5782         if (!NT_STATUS_IS_OK(status)) {
5783                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5784                 goto fail;
5785         }
5786
5787         /* This should fail - no more opens once delete on close set. */
5788         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5789                               FILE_ATTRIBUTE_NORMAL,
5790                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5791                               FILE_OPEN, 0, 0, &fnum2, NULL);
5792         if (NT_STATUS_IS_OK(status)) {
5793                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5794                 goto fail;
5795         }
5796
5797         status = cli_nt_delete_on_close(cli1, fnum1, false);
5798         if (!NT_STATUS_IS_OK(status)) {
5799                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5800                 goto fail;
5801         }
5802
5803         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5804                               FILE_ATTRIBUTE_NORMAL,
5805                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5806                               FILE_OPEN, 0, 0, &fnum2, NULL);
5807         if (!NT_STATUS_IS_OK(status)) {
5808                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5809                 goto fail;
5810         }
5811
5812         status = cli_close(cli1, fnum2);
5813         if (!NT_STATUS_IS_OK(status)) {
5814                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5815                 goto fail;
5816         }
5817
5818         status = cli_close(cli1, fnum1);
5819         if (!NT_STATUS_IS_OK(status)) {
5820                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5821                 goto fail;
5822         }
5823
5824         /*
5825          * setting delete on close on the handle does
5826          * not unset the initial delete on close...
5827          */
5828         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5829                               FILE_ATTRIBUTE_NORMAL,
5830                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5831                               FILE_OPEN, 0, 0, &fnum2, NULL);
5832         if (NT_STATUS_IS_OK(status)) {
5833                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5834                 goto fail;
5835         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5836                 printf("ntcreate returned %s, expected "
5837                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5838                        nt_errstr(status));
5839                 goto fail;
5840         }
5841
5842         printf("twelfth delete on close test succeeded.\n");
5843
5844
5845         printf("finished delete test\n");
5846
5847         correct = true;
5848
5849   fail:
5850         /* FIXME: This will crash if we aborted before cli2 got
5851          * intialized, because these functions don't handle
5852          * uninitialized connections. */
5853
5854         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5855         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5856         cli_setatr(cli1, fname, 0, 0);
5857         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5858
5859         if (cli1 && !torture_close_connection(cli1)) {
5860                 correct = False;
5861         }
5862         if (cli2 && !torture_close_connection(cli2)) {
5863                 correct = False;
5864         }
5865         return correct;
5866 }
5867
5868 struct delete_stream_state {
5869         bool closed;
5870 };
5871
5872 static void delete_stream_unlinked(struct tevent_req *subreq);
5873 static void delete_stream_closed(struct tevent_req *subreq);
5874
5875 static struct tevent_req *delete_stream_send(
5876         TALLOC_CTX *mem_ctx,
5877         struct tevent_context *ev,
5878         struct cli_state *cli,
5879         const char *base_fname,
5880         uint16_t stream_fnum)
5881 {
5882         struct tevent_req *req = NULL, *subreq = NULL;
5883         struct delete_stream_state *state = NULL;
5884
5885         req = tevent_req_create(
5886                 mem_ctx, &state, struct delete_stream_state);
5887         if (req == NULL) {
5888                 return NULL;
5889         }
5890
5891         subreq = cli_unlink_send(
5892                 state,
5893                 ev,
5894                 cli,
5895                 base_fname,
5896                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5897         if (tevent_req_nomem(subreq, req)) {
5898                 return tevent_req_post(req, ev);
5899         }
5900         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5901
5902         subreq = cli_close_send(state, ev, cli, stream_fnum);
5903         if (tevent_req_nomem(subreq, req)) {
5904                 return tevent_req_post(req, ev);
5905         }
5906         tevent_req_set_callback(subreq, delete_stream_closed, req);
5907
5908         return req;
5909 }
5910
5911 static void delete_stream_unlinked(struct tevent_req *subreq)
5912 {
5913         struct tevent_req *req = tevent_req_callback_data(
5914                 subreq, struct tevent_req);
5915         struct delete_stream_state *state = tevent_req_data(
5916                 req, struct delete_stream_state);
5917         NTSTATUS status;
5918
5919         status = cli_unlink_recv(subreq);
5920         TALLOC_FREE(subreq);
5921         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5922                 printf("cli_unlink returned %s\n",
5923                        nt_errstr(status));
5924                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5925                 return;
5926         }
5927         if (!state->closed) {
5928                 /* close reply should have come in first */
5929                 printf("Not closed\n");
5930                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5931                 return;
5932         }
5933         tevent_req_done(req);
5934 }
5935
5936 static void delete_stream_closed(struct tevent_req *subreq)
5937 {
5938         struct tevent_req *req = tevent_req_callback_data(
5939                 subreq, struct tevent_req);
5940         struct delete_stream_state *state = tevent_req_data(
5941                 req, struct delete_stream_state);
5942         NTSTATUS status;
5943
5944         status = cli_close_recv(subreq);
5945         TALLOC_FREE(subreq);
5946         if (tevent_req_nterror(req, status)) {
5947                 return;
5948         }
5949         /* also waiting for the unlink to come back */
5950         state->closed = true;
5951 }
5952
5953 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5954 {
5955         return tevent_req_simple_recv_ntstatus(req);
5956 }
5957
5958 static bool run_delete_stream(int dummy)
5959 {
5960         struct tevent_context *ev = NULL;
5961         struct tevent_req *req = NULL;
5962         struct cli_state *cli = NULL;
5963         const char fname[] = "delete_stream";
5964         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5965         uint16_t fnum1, fnum2;
5966         NTSTATUS status;
5967         bool ok;
5968
5969         printf("Starting stream delete test\n");
5970
5971         ok = torture_open_connection(&cli, 0);
5972         if (!ok) {
5973                 return false;
5974         }
5975
5976         cli_setatr(cli, fname, 0, 0);
5977         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5978
5979         /* Create the file. */
5980         status = cli_ntcreate(
5981                 cli,
5982                 fname,
5983                 0,
5984                 READ_CONTROL_ACCESS,
5985                 0,
5986                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5987                 FILE_CREATE,
5988                 0x0,
5989                 0x0,
5990                 &fnum1,
5991                 NULL);
5992         if (!NT_STATUS_IS_OK(status)) {
5993                 d_fprintf(stderr,
5994                           "cli_ntcreate of %s failed (%s)\n",
5995                           fname,
5996                           nt_errstr(status));
5997                 return false;
5998         }
5999         status = cli_close(cli, fnum1);
6000         if (!NT_STATUS_IS_OK(status)) {
6001                 d_fprintf(stderr,
6002                           "cli_close of %s failed (%s)\n",
6003                           fname,
6004                           nt_errstr(status));
6005                 return false;
6006         }
6007
6008         /* Now create the stream. */
6009         status = cli_ntcreate(
6010                 cli,
6011                 fname_stream,
6012                 0,
6013                 FILE_WRITE_DATA,
6014                 0,
6015                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6016                 FILE_CREATE,
6017                 0x0,
6018                 0x0,
6019                 &fnum1,
6020                 NULL);
6021
6022         if (!NT_STATUS_IS_OK(status)) {
6023                 d_fprintf(stderr,
6024                           "cli_ntcreate of %s failed (%s)\n",
6025                           fname_stream,
6026                           nt_errstr(status));
6027                 return false;
6028         }
6029
6030         /* open it a second time */
6031
6032         status = cli_ntcreate(
6033                 cli,
6034                 fname_stream,
6035                 0,
6036                 FILE_WRITE_DATA,
6037                 0,
6038                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6039                 FILE_OPEN,
6040                 0x0,
6041                 0x0,
6042                 &fnum2,
6043                 NULL);
6044
6045         if (!NT_STATUS_IS_OK(status)) {
6046                 d_fprintf(stderr,
6047                           "2nd cli_ntcreate of %s failed (%s)\n",
6048                           fname_stream,
6049                           nt_errstr(status));
6050                 return false;
6051         }
6052
6053         ev = samba_tevent_context_init(talloc_tos());
6054         if (ev == NULL) {
6055                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6056                 return false;
6057         }
6058
6059         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6060         if (req == NULL) {
6061                 d_fprintf(stderr, "delete_stream_send failed\n");
6062                 return false;
6063         }
6064
6065         ok = tevent_req_poll_ntstatus(req, ev, &status);
6066         if (!ok) {
6067                 d_fprintf(stderr,
6068                           "tevent_req_poll_ntstatus failed: %s\n",
6069                           nt_errstr(status));
6070                 return false;
6071         }
6072
6073         status = delete_stream_recv(req);
6074         TALLOC_FREE(req);
6075         if (!NT_STATUS_IS_OK(status)) {
6076                 d_fprintf(stderr,
6077                           "delete_stream failed: %s\n",
6078                           nt_errstr(status));
6079                 return false;
6080         }
6081
6082         status = cli_close(cli, fnum2);
6083         if (!NT_STATUS_IS_OK(status)) {
6084                 d_fprintf(stderr,
6085                           "close failed: %s\n",
6086                           nt_errstr(status));
6087                 return false;
6088         }
6089
6090         status = cli_unlink(
6091                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6092         if (!NT_STATUS_IS_OK(status)) {
6093                 d_fprintf(stderr,
6094                           "unlink failed: %s\n",
6095                           nt_errstr(status));
6096                 return false;
6097         }
6098
6099         return true;
6100 }
6101
6102 /*
6103   Exercise delete on close semantics - use on the PRINT1 share in torture
6104   testing.
6105  */
6106 static bool run_delete_print_test(int dummy)
6107 {
6108         struct cli_state *cli1 = NULL;
6109         const char *fname = "print_delete.file";
6110         uint16_t fnum1 = (uint16_t)-1;
6111         bool correct = false;
6112         const char *buf = "print file data\n";
6113         NTSTATUS status;
6114
6115         printf("starting print delete test\n");
6116
6117         if (!torture_open_connection(&cli1, 0)) {
6118                 return false;
6119         }
6120
6121         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6122
6123         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6124                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6125                               0, 0, &fnum1, NULL);
6126         if (!NT_STATUS_IS_OK(status)) {
6127                 printf("open of %s failed (%s)\n",
6128                         fname,
6129                         nt_errstr(status));
6130                 goto fail;
6131         }
6132
6133         status = cli_writeall(cli1,
6134                         fnum1,
6135                         0,
6136                         (const uint8_t *)buf,
6137                         0, /* offset */
6138                         strlen(buf), /* size */
6139                         NULL);
6140         if (!NT_STATUS_IS_OK(status)) {
6141                 printf("writing print file data failed (%s)\n",
6142                         nt_errstr(status));
6143                 goto fail;
6144         }
6145
6146         status = cli_nt_delete_on_close(cli1, fnum1, true);
6147         if (!NT_STATUS_IS_OK(status)) {
6148                 printf("setting delete_on_close failed (%s)\n",
6149                         nt_errstr(status));
6150                 goto fail;
6151         }
6152
6153         status = cli_close(cli1, fnum1);
6154         if (!NT_STATUS_IS_OK(status)) {
6155                 printf("close failed (%s)\n", nt_errstr(status));
6156                 goto fail;
6157         }
6158
6159         printf("finished print delete test\n");
6160
6161         correct = true;
6162
6163   fail:
6164
6165         if (fnum1 != (uint16_t)-1) {
6166                 cli_close(cli1, fnum1);
6167         }
6168
6169         if (cli1 && !torture_close_connection(cli1)) {
6170                 correct = false;
6171         }
6172         return correct;
6173 }
6174
6175 static bool run_deletetest_ln(int dummy)
6176 {
6177         struct cli_state *cli;
6178         const char *fname = "\\delete1";
6179         const char *fname_ln = "\\delete1_ln";
6180         uint16_t fnum;
6181         uint16_t fnum1;
6182         NTSTATUS status;
6183         bool correct = true;
6184         time_t t;
6185
6186         printf("starting deletetest-ln\n");
6187
6188         if (!torture_open_connection(&cli, 0)) {
6189                 return false;
6190         }
6191
6192         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6193         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6194
6195         smbXcli_conn_set_sockopt(cli->conn, sockops);
6196
6197         /* Create the file. */
6198         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6199         if (!NT_STATUS_IS_OK(status)) {
6200                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6201                 return false;
6202         }
6203
6204         status = cli_close(cli, fnum);
6205         if (!NT_STATUS_IS_OK(status)) {
6206                 printf("close1 failed (%s)\n", nt_errstr(status));
6207                 return false;
6208         }
6209
6210         /* Now create a hardlink. */
6211         status = cli_hardlink(cli, fname, fname_ln);
6212         if (!NT_STATUS_IS_OK(status)) {
6213                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6214                 return false;
6215         }
6216
6217         /* Open the original file. */
6218         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6219                         FILE_ATTRIBUTE_NORMAL,
6220                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6221                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6222         if (!NT_STATUS_IS_OK(status)) {
6223                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6224                 return false;
6225         }
6226
6227         /* Unlink the hard link path. */
6228         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6229                         FILE_ATTRIBUTE_NORMAL,
6230                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6231                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6232         if (!NT_STATUS_IS_OK(status)) {
6233                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6234                 return false;
6235         }
6236         status = cli_nt_delete_on_close(cli, fnum1, true);
6237         if (!NT_STATUS_IS_OK(status)) {
6238                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6239                         __location__, fname_ln, nt_errstr(status));
6240                 return false;
6241         }
6242
6243         status = cli_close(cli, fnum1);
6244         if (!NT_STATUS_IS_OK(status)) {
6245                 printf("close %s failed (%s)\n",
6246                         fname_ln, nt_errstr(status));
6247                 return false;
6248         }
6249
6250         status = cli_close(cli, fnum);
6251         if (!NT_STATUS_IS_OK(status)) {
6252                 printf("close %s failed (%s)\n",
6253                         fname, nt_errstr(status));
6254                 return false;
6255         }
6256
6257         /* Ensure the original file is still there. */
6258         status = cli_getatr(cli, fname, NULL, NULL, &t);
6259         if (!NT_STATUS_IS_OK(status)) {
6260                 printf("%s getatr on file %s failed (%s)\n",
6261                         __location__,
6262                         fname,
6263                         nt_errstr(status));
6264                 correct = False;
6265         }
6266
6267         /* Ensure the link path is gone. */
6268         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6269         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6270                 printf("%s, getatr for file %s returned wrong error code %s "
6271                         "- should have been deleted\n",
6272                         __location__,
6273                         fname_ln, nt_errstr(status));
6274                 correct = False;
6275         }
6276
6277         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6278         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6279
6280         if (!torture_close_connection(cli)) {
6281                 correct = false;
6282         }
6283
6284         printf("finished deletetest-ln\n");
6285
6286         return correct;
6287 }
6288
6289 /*
6290   print out server properties
6291  */
6292 static bool run_properties(int dummy)
6293 {
6294         struct cli_state *cli;
6295         bool correct = True;
6296
6297         printf("starting properties test\n");
6298
6299         ZERO_STRUCT(cli);
6300
6301         if (!torture_open_connection(&cli, 0)) {
6302                 return False;
6303         }
6304
6305         smbXcli_conn_set_sockopt(cli->conn, sockops);
6306
6307         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6308
6309         if (!torture_close_connection(cli)) {
6310                 correct = False;
6311         }
6312
6313         return correct;
6314 }
6315
6316
6317
6318 /* FIRST_DESIRED_ACCESS   0xf019f */
6319 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6320                                FILE_READ_EA|                           /* 0xf */ \
6321                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6322                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6323                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6324                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6325 /* SECOND_DESIRED_ACCESS  0xe0080 */
6326 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6327                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6328                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6329
6330 #if 0
6331 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6332                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6333                                FILE_READ_DATA|\
6334                                WRITE_OWNER_ACCESS                      /* */
6335 #endif
6336
6337 /*
6338   Test ntcreate calls made by xcopy
6339  */
6340 static bool run_xcopy(int dummy)
6341 {
6342         static struct cli_state *cli1;
6343         const char *fname = "\\test.txt";
6344         bool correct = True;
6345         uint16_t fnum1, fnum2;
6346         NTSTATUS status;
6347
6348         printf("starting xcopy test\n");
6349
6350         if (!torture_open_connection(&cli1, 0)) {
6351                 return False;
6352         }
6353
6354         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6355                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6356                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6357         if (!NT_STATUS_IS_OK(status)) {
6358                 printf("First open failed - %s\n", nt_errstr(status));
6359                 return False;
6360         }
6361
6362         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6363                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6364                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6365         if (!NT_STATUS_IS_OK(status)) {
6366                 printf("second open failed - %s\n", nt_errstr(status));
6367                 return False;
6368         }
6369
6370         if (!torture_close_connection(cli1)) {
6371                 correct = False;
6372         }
6373
6374         return correct;
6375 }
6376
6377 /*
6378   Test rename on files open with share delete and no share delete.
6379  */
6380 static bool run_rename(int dummy)
6381 {
6382         static struct cli_state *cli1;
6383         const char *fname = "\\test.txt";
6384         const char *fname1 = "\\test1.txt";
6385         bool correct = True;
6386         uint16_t fnum1;
6387         uint32_t attr;
6388         NTSTATUS status;
6389
6390         printf("starting rename test\n");
6391
6392         if (!torture_open_connection(&cli1, 0)) {
6393                 return False;
6394         }
6395
6396         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6397         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6398
6399         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6400                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6401                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6402         if (!NT_STATUS_IS_OK(status)) {
6403                 printf("First open failed - %s\n", nt_errstr(status));
6404                 return False;
6405         }
6406
6407         status = cli_rename(cli1, fname, fname1, false);
6408         if (!NT_STATUS_IS_OK(status)) {
6409                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6410         } else {
6411                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6412                 correct = False;
6413         }
6414
6415         status = cli_close(cli1, fnum1);
6416         if (!NT_STATUS_IS_OK(status)) {
6417                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6418                 return False;
6419         }
6420
6421         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6422         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6423         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6424 #if 0
6425                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6426 #else
6427                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6428 #endif
6429                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6430         if (!NT_STATUS_IS_OK(status)) {
6431                 printf("Second open failed - %s\n", nt_errstr(status));
6432                 return False;
6433         }
6434
6435         status = cli_rename(cli1, fname, fname1, false);
6436         if (!NT_STATUS_IS_OK(status)) {
6437                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6438                 correct = False;
6439         } else {
6440                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6441         }
6442
6443         status = cli_close(cli1, fnum1);
6444         if (!NT_STATUS_IS_OK(status)) {
6445                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6446                 return False;
6447         }
6448
6449         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6450         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6451
6452         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6453                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6454                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6455         if (!NT_STATUS_IS_OK(status)) {
6456                 printf("Third open failed - %s\n", nt_errstr(status));
6457                 return False;
6458         }
6459
6460
6461         status = cli_rename(cli1, fname, fname1, false);
6462         if (!NT_STATUS_IS_OK(status)) {
6463                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6464                 correct = False;
6465         } else {
6466                 printf("Third rename succeeded (SHARE_NONE)\n");
6467         }
6468
6469         status = cli_close(cli1, fnum1);
6470         if (!NT_STATUS_IS_OK(status)) {
6471                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6472                 return False;
6473         }
6474
6475         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6476         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6477
6478         /*----*/
6479
6480         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6481                               FILE_ATTRIBUTE_NORMAL,
6482                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6483                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6484         if (!NT_STATUS_IS_OK(status)) {
6485                 printf("Fourth open failed - %s\n", nt_errstr(status));
6486                 return False;
6487         }
6488
6489         status = cli_rename(cli1, fname, fname1, false);
6490         if (!NT_STATUS_IS_OK(status)) {
6491                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6492         } else {
6493                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6494                 correct = False;
6495         }
6496
6497         status = cli_close(cli1, fnum1);
6498         if (!NT_STATUS_IS_OK(status)) {
6499                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6500                 return False;
6501         }
6502
6503         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6504         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6505
6506         /*--*/
6507
6508         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6509                          FILE_ATTRIBUTE_NORMAL,
6510                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6511                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6512         if (!NT_STATUS_IS_OK(status)) {
6513                 printf("Fifth open failed - %s\n", nt_errstr(status));
6514                 return False;
6515         }
6516
6517         status = cli_rename(cli1, fname, fname1, false);
6518         if (!NT_STATUS_IS_OK(status)) {
6519                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6520                 correct = False;
6521         } else {
6522                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6523         }
6524
6525         /*--*/
6526         status = cli_close(cli1, fnum1);
6527         if (!NT_STATUS_IS_OK(status)) {
6528                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6529                 return False;
6530         }
6531
6532         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6533         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6534         if (!NT_STATUS_IS_OK(status)) {
6535                 printf("getatr on file %s failed - %s ! \n",
6536                         fname1, nt_errstr(status));
6537                 correct = False;
6538         } else {
6539                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6540                         printf("Renamed file %s has wrong attr 0x%x "
6541                                 "(should be 0x%x)\n",
6542                                 fname1,
6543                                 attr,
6544                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6545                         correct = False;
6546                 } else {
6547                         printf("Renamed file %s has archive bit set\n", fname1);
6548                 }
6549         }
6550
6551         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6552         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6553
6554         if (!torture_close_connection(cli1)) {
6555                 correct = False;
6556         }
6557
6558         return correct;
6559 }
6560
6561 /*
6562   Test rename into a directory with an ACL denying it.
6563  */
6564 static bool run_rename_access(int dummy)
6565 {
6566         static struct cli_state *cli = NULL;
6567         static struct cli_state *posix_cli = NULL;
6568         const char *src = "test.txt";
6569         const char *dname = "dir";
6570         const char *dst = "dir\\test.txt";
6571         const char *dsrc = "test.dir";
6572         const char *ddst = "dir\\test.dir";
6573         uint16_t fnum = (uint16_t)-1;
6574         struct security_descriptor *sd = NULL;
6575         struct security_descriptor *newsd = NULL;
6576         NTSTATUS status;
6577         TALLOC_CTX *frame = NULL;
6578
6579         frame = talloc_stackframe();
6580         printf("starting rename access test\n");
6581
6582         /* Windows connection. */
6583         if (!torture_open_connection(&cli, 0)) {
6584                 goto fail;
6585         }
6586
6587         smbXcli_conn_set_sockopt(cli->conn, sockops);
6588
6589         /* Posix connection. */
6590         if (!torture_open_connection(&posix_cli, 0)) {
6591                 goto fail;
6592         }
6593
6594         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6595
6596         status = torture_setup_unix_extensions(posix_cli);
6597         if (!NT_STATUS_IS_OK(status)) {
6598                 goto fail;
6599         }
6600
6601         /* Start with a clean slate. */
6602         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6603         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6604         cli_rmdir(cli, dsrc);
6605         cli_rmdir(cli, ddst);
6606         cli_rmdir(cli, dname);
6607
6608         /*
6609          * Setup the destination directory with a DENY ACE to
6610          * prevent new files within it.
6611          */
6612         status = cli_ntcreate(cli,
6613                                 dname,
6614                                 0,
6615                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6616                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6617                                         WRITE_OWNER_ACCESS,
6618                                 FILE_ATTRIBUTE_DIRECTORY,
6619                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6620                                 FILE_CREATE,
6621                                 FILE_DIRECTORY_FILE,
6622                                 0,
6623                                 &fnum,
6624                                 NULL);
6625         if (!NT_STATUS_IS_OK(status)) {
6626                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6627                 goto fail;
6628         }
6629
6630         status = cli_query_secdesc(cli,
6631                                 fnum,
6632                                 frame,
6633                                 &sd);
6634         if (!NT_STATUS_IS_OK(status)) {
6635                 printf("cli_query_secdesc failed for %s (%s)\n",
6636                         dname, nt_errstr(status));
6637                 goto fail;
6638         }
6639
6640         newsd = security_descriptor_dacl_create(frame,
6641                                         0,
6642                                         NULL,
6643                                         NULL,
6644                                         SID_WORLD,
6645                                         SEC_ACE_TYPE_ACCESS_DENIED,
6646                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6647                                         0,
6648                                         NULL);
6649         if (newsd == NULL) {
6650                 goto fail;
6651         }
6652         sd->dacl = security_acl_concatenate(frame,
6653                                         newsd->dacl,
6654                                         sd->dacl);
6655         if (sd->dacl == NULL) {
6656                 goto fail;
6657         }
6658         status = cli_set_secdesc(cli, fnum, sd);
6659         if (!NT_STATUS_IS_OK(status)) {
6660                 printf("cli_set_secdesc failed for %s (%s)\n",
6661                         dname, nt_errstr(status));
6662                 goto fail;
6663         }
6664         status = cli_close(cli, fnum);
6665         if (!NT_STATUS_IS_OK(status)) {
6666                 printf("close failed for %s (%s)\n",
6667                         dname, nt_errstr(status));
6668                 goto fail;
6669         }
6670         /* Now go around the back and chmod to 777 via POSIX. */
6671         status = cli_posix_chmod(posix_cli, dname, 0777);
6672         if (!NT_STATUS_IS_OK(status)) {
6673                 printf("cli_posix_chmod failed for %s (%s)\n",
6674                         dname, nt_errstr(status));
6675                 goto fail;
6676         }
6677
6678         /* Check we can't create a file within dname via Windows. */
6679         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6680         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6681                 cli_close(posix_cli, fnum);
6682                 printf("Create of %s should be ACCESS denied, was %s\n",
6683                         dst, nt_errstr(status));
6684                 goto fail;
6685         }
6686
6687         /* Make the sample file/directory. */
6688         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6689         if (!NT_STATUS_IS_OK(status)) {
6690                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6691                 goto fail;
6692         }
6693         status = cli_close(cli, fnum);
6694         if (!NT_STATUS_IS_OK(status)) {
6695                 printf("cli_close failed (%s)\n", nt_errstr(status));
6696                 goto fail;
6697         }
6698
6699         status = cli_mkdir(cli, dsrc);
6700         if (!NT_STATUS_IS_OK(status)) {
6701                 printf("cli_mkdir of %s failed (%s)\n",
6702                         dsrc, nt_errstr(status));
6703                 goto fail;
6704         }
6705
6706         /*
6707          * OK - renames of the new file and directory into the
6708          * dst directory should fail.
6709          */
6710
6711         status = cli_rename(cli, src, dst, false);
6712         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6713                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6714                         src, dst, nt_errstr(status));
6715                 goto fail;
6716         }
6717         status = cli_rename(cli, dsrc, ddst, false);
6718         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6719                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6720                         src, dst, nt_errstr(status));
6721                 goto fail;
6722         }
6723
6724         TALLOC_FREE(frame);
6725         return true;
6726
6727   fail:
6728
6729         if (posix_cli) {
6730                 torture_close_connection(posix_cli);
6731         }
6732
6733         if (cli) {
6734                 if (fnum != (uint16_t)-1) {
6735                         cli_close(cli, fnum);
6736                 }
6737                 cli_unlink(cli, src,
6738                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6739                 cli_unlink(cli, dst,
6740                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6741                 cli_rmdir(cli, dsrc);
6742                 cli_rmdir(cli, ddst);
6743                 cli_rmdir(cli, dname);
6744
6745                 torture_close_connection(cli);
6746         }
6747
6748         TALLOC_FREE(frame);
6749         return false;
6750 }
6751
6752 /*
6753   Test owner rights ACE.
6754  */
6755 static bool run_owner_rights(int dummy)
6756 {
6757         static struct cli_state *cli = NULL;
6758         const char *fname = "owner_rights.txt";
6759         uint16_t fnum = (uint16_t)-1;
6760         struct security_descriptor *sd = NULL;
6761         struct security_descriptor *newsd = NULL;
6762         NTSTATUS status;
6763         TALLOC_CTX *frame = NULL;
6764
6765         frame = talloc_stackframe();
6766         printf("starting owner rights test\n");
6767
6768         /* Windows connection. */
6769         if (!torture_open_connection(&cli, 0)) {
6770                 goto fail;
6771         }
6772
6773         smbXcli_conn_set_sockopt(cli->conn, sockops);
6774
6775         /* Start with a clean slate. */
6776         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6777
6778         /* Create the test file. */
6779         /* Now try and open for read and write-dac. */
6780         status = cli_ntcreate(cli,
6781                                 fname,
6782                                 0,
6783                                 GENERIC_ALL_ACCESS,
6784                                 FILE_ATTRIBUTE_NORMAL,
6785                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6786                                         FILE_SHARE_DELETE,
6787                                 FILE_CREATE,
6788                                 0,
6789                                 0,
6790                                 &fnum,
6791                                 NULL);
6792         if (!NT_STATUS_IS_OK(status)) {
6793                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6794                 goto fail;
6795         }
6796
6797         /* Get the original SD. */
6798         status = cli_query_secdesc(cli,
6799                                 fnum,
6800                                 frame,
6801                                 &sd);
6802         if (!NT_STATUS_IS_OK(status)) {
6803                 printf("cli_query_secdesc failed for %s (%s)\n",
6804                         fname, nt_errstr(status));
6805                 goto fail;
6806         }
6807
6808         /*
6809          * Add an "owner-rights" ACE denying WRITE_DATA,
6810          * and an "owner-rights" ACE allowing READ_DATA.
6811          */
6812
6813         newsd = security_descriptor_dacl_create(frame,
6814                                         0,
6815                                         NULL,
6816                                         NULL,
6817                                         SID_OWNER_RIGHTS,
6818                                         SEC_ACE_TYPE_ACCESS_DENIED,
6819                                         FILE_WRITE_DATA,
6820                                         0,
6821                                         SID_OWNER_RIGHTS,
6822                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6823                                         FILE_READ_DATA,
6824                                         0,
6825                                         NULL);
6826         if (newsd == NULL) {
6827                 goto fail;
6828         }
6829         sd->dacl = security_acl_concatenate(frame,
6830                                         newsd->dacl,
6831                                         sd->dacl);
6832         if (sd->dacl == NULL) {
6833                 goto fail;
6834         }
6835         status = cli_set_secdesc(cli, fnum, sd);
6836         if (!NT_STATUS_IS_OK(status)) {
6837                 printf("cli_set_secdesc failed for %s (%s)\n",
6838                         fname, nt_errstr(status));
6839                 goto fail;
6840         }
6841         status = cli_close(cli, fnum);
6842         if (!NT_STATUS_IS_OK(status)) {
6843                 printf("close failed for %s (%s)\n",
6844                         fname, nt_errstr(status));
6845                 goto fail;
6846         }
6847         fnum = (uint16_t)-1;
6848
6849         /* Try and open for FILE_WRITE_DATA */
6850         status = cli_ntcreate(cli,
6851                                 fname,
6852                                 0,
6853                                 FILE_WRITE_DATA,
6854                                 FILE_ATTRIBUTE_NORMAL,
6855                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6856                                         FILE_SHARE_DELETE,
6857                                 FILE_OPEN,
6858                                 0,
6859                                 0,
6860                                 &fnum,
6861                                 NULL);
6862         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6863                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6864                 goto fail;
6865         }
6866
6867         /* Now try and open for FILE_READ_DATA */
6868         status = cli_ntcreate(cli,
6869                                 fname,
6870                                 0,
6871                                 FILE_READ_DATA,
6872                                 FILE_ATTRIBUTE_NORMAL,
6873                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6874                                         FILE_SHARE_DELETE,
6875                                 FILE_OPEN,
6876                                 0,
6877                                 0,
6878                                 &fnum,
6879                                 NULL);
6880         if (!NT_STATUS_IS_OK(status)) {
6881                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6882                 goto fail;
6883         }
6884
6885         status = cli_close(cli, fnum);
6886         if (!NT_STATUS_IS_OK(status)) {
6887                 printf("close failed for %s (%s)\n",
6888                         fname, nt_errstr(status));
6889                 goto fail;
6890         }
6891
6892         /* Restore clean slate. */
6893         TALLOC_FREE(sd);
6894         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6895
6896         /* Create the test file. */
6897         status = cli_ntcreate(cli,
6898                                 fname,
6899                                 0,
6900                                 GENERIC_ALL_ACCESS,
6901                                 FILE_ATTRIBUTE_NORMAL,
6902                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6903                                         FILE_SHARE_DELETE,
6904                                 FILE_CREATE,
6905                                 0,
6906                                 0,
6907                                 &fnum,
6908                                 NULL);
6909         if (!NT_STATUS_IS_OK(status)) {
6910                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6911                 goto fail;
6912         }
6913
6914         /* Get the original SD. */
6915         status = cli_query_secdesc(cli,
6916                                 fnum,
6917                                 frame,
6918                                 &sd);
6919         if (!NT_STATUS_IS_OK(status)) {
6920                 printf("cli_query_secdesc failed for %s (%s)\n",
6921                         fname, nt_errstr(status));
6922                 goto fail;
6923         }
6924
6925         /*
6926          * Add an "owner-rights ACE denying WRITE_DATA,
6927          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6928          */
6929
6930         newsd = security_descriptor_dacl_create(frame,
6931                                         0,
6932                                         NULL,
6933                                         NULL,
6934                                         SID_OWNER_RIGHTS,
6935                                         SEC_ACE_TYPE_ACCESS_DENIED,
6936                                         FILE_WRITE_DATA,
6937                                         0,
6938                                         SID_OWNER_RIGHTS,
6939                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6940                                         FILE_READ_DATA|FILE_WRITE_DATA,
6941                                         0,
6942                                         NULL);
6943         if (newsd == NULL) {
6944                 goto fail;
6945         }
6946         sd->dacl = security_acl_concatenate(frame,
6947                                         newsd->dacl,
6948                                         sd->dacl);
6949         if (sd->dacl == NULL) {
6950                 goto fail;
6951         }
6952         status = cli_set_secdesc(cli, fnum, sd);
6953         if (!NT_STATUS_IS_OK(status)) {
6954                 printf("cli_set_secdesc failed for %s (%s)\n",
6955                         fname, nt_errstr(status));
6956                 goto fail;
6957         }
6958         status = cli_close(cli, fnum);
6959         if (!NT_STATUS_IS_OK(status)) {
6960                 printf("close failed for %s (%s)\n",
6961                         fname, nt_errstr(status));
6962                 goto fail;
6963         }
6964         fnum = (uint16_t)-1;
6965
6966         /* Try and open for FILE_WRITE_DATA */
6967         status = cli_ntcreate(cli,
6968                                 fname,
6969                                 0,
6970                                 FILE_WRITE_DATA,
6971                                 FILE_ATTRIBUTE_NORMAL,
6972                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6973                                         FILE_SHARE_DELETE,
6974                                 FILE_OPEN,
6975                                 0,
6976                                 0,
6977                                 &fnum,
6978                                 NULL);
6979         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6980                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6981                 goto fail;
6982         }
6983
6984         /* Now try and open for FILE_READ_DATA */
6985         status = cli_ntcreate(cli,
6986                                 fname,
6987                                 0,
6988                                 FILE_READ_DATA,
6989                                 FILE_ATTRIBUTE_NORMAL,
6990                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6991                                         FILE_SHARE_DELETE,
6992                                 FILE_OPEN,
6993                                 0,
6994                                 0,
6995                                 &fnum,
6996                                 NULL);
6997         if (!NT_STATUS_IS_OK(status)) {
6998                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6999                 goto fail;
7000         }
7001
7002         status = cli_close(cli, fnum);
7003         if (!NT_STATUS_IS_OK(status)) {
7004                 printf("close failed for %s (%s)\n",
7005                         fname, nt_errstr(status));
7006                 goto fail;
7007         }
7008
7009         /* Restore clean slate. */
7010         TALLOC_FREE(sd);
7011         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7012
7013
7014         /* Create the test file. */
7015         status = cli_ntcreate(cli,
7016                                 fname,
7017                                 0,
7018                                 GENERIC_ALL_ACCESS,
7019                                 FILE_ATTRIBUTE_NORMAL,
7020                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7021                                         FILE_SHARE_DELETE,
7022                                 FILE_CREATE,
7023                                 0,
7024                                 0,
7025                                 &fnum,
7026                                 NULL);
7027         if (!NT_STATUS_IS_OK(status)) {
7028                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7029                 goto fail;
7030         }
7031
7032         /* Get the original SD. */
7033         status = cli_query_secdesc(cli,
7034                                 fnum,
7035                                 frame,
7036                                 &sd);
7037         if (!NT_STATUS_IS_OK(status)) {
7038                 printf("cli_query_secdesc failed for %s (%s)\n",
7039                         fname, nt_errstr(status));
7040                 goto fail;
7041         }
7042
7043         /*
7044          * Add an "authenticated users" ACE allowing READ_DATA,
7045          * add an "owner-rights" denying READ_DATA,
7046          * and an "authenticated users" ACE allowing WRITE_DATA.
7047          */
7048
7049         newsd = security_descriptor_dacl_create(frame,
7050                                         0,
7051                                         NULL,
7052                                         NULL,
7053                                         SID_NT_AUTHENTICATED_USERS,
7054                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7055                                         FILE_READ_DATA,
7056                                         0,
7057                                         SID_OWNER_RIGHTS,
7058                                         SEC_ACE_TYPE_ACCESS_DENIED,
7059                                         FILE_READ_DATA,
7060                                         0,
7061                                         SID_NT_AUTHENTICATED_USERS,
7062                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7063                                         FILE_WRITE_DATA,
7064                                         0,
7065                                         NULL);
7066         if (newsd == NULL) {
7067                 printf("newsd == NULL\n");
7068                 goto fail;
7069         }
7070         sd->dacl = security_acl_concatenate(frame,
7071                                         newsd->dacl,
7072                                         sd->dacl);
7073         if (sd->dacl == NULL) {
7074                 printf("sd->dacl == NULL\n");
7075                 goto fail;
7076         }
7077         status = cli_set_secdesc(cli, fnum, sd);
7078         if (!NT_STATUS_IS_OK(status)) {
7079                 printf("cli_set_secdesc failed for %s (%s)\n",
7080                         fname, nt_errstr(status));
7081                 goto fail;
7082         }
7083         status = cli_close(cli, fnum);
7084         if (!NT_STATUS_IS_OK(status)) {
7085                 printf("close failed for %s (%s)\n",
7086                         fname, nt_errstr(status));
7087                 goto fail;
7088         }
7089         fnum = (uint16_t)-1;
7090
7091         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7092         status = cli_ntcreate(cli,
7093                                 fname,
7094                                 0,
7095                                 FILE_READ_DATA|FILE_WRITE_DATA,
7096                                 FILE_ATTRIBUTE_NORMAL,
7097                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7098                                         FILE_SHARE_DELETE,
7099                                 FILE_OPEN,
7100                                 0,
7101                                 0,
7102                                 &fnum,
7103                                 NULL);
7104         if (!NT_STATUS_IS_OK(status)) {
7105                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7106                 goto fail;
7107         }
7108
7109         status = cli_close(cli, fnum);
7110         if (!NT_STATUS_IS_OK(status)) {
7111                 printf("close failed for %s (%s)\n",
7112                         fname, nt_errstr(status));
7113                 goto fail;
7114         }
7115
7116         cli_unlink(cli, fname,
7117                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7118
7119         TALLOC_FREE(frame);
7120         return true;
7121
7122   fail:
7123
7124         if (cli) {
7125                 if (fnum != (uint16_t)-1) {
7126                         cli_close(cli, fnum);
7127                 }
7128                 cli_unlink(cli, fname,
7129                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7130                 torture_close_connection(cli);
7131         }
7132
7133         TALLOC_FREE(frame);
7134         return false;
7135 }
7136
7137 /*
7138  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7139  * Note this test only works with a user with SeSecurityPrivilege set.
7140  *
7141  * NB. This is also tested in samba3.base.createx_access
7142  * but this makes it very explicit what we're looking for.
7143  */
7144 static bool run_smb1_system_security(int dummy)
7145 {
7146         static struct cli_state *cli = NULL;
7147         const char *fname = "system_security.txt";
7148         uint16_t fnum = (uint16_t)-1;
7149         NTSTATUS status;
7150         TALLOC_CTX *frame = NULL;
7151
7152         frame = talloc_stackframe();
7153         printf("starting smb1 system security test\n");
7154
7155         /* SMB1 connection - torture_open_connection() forces this. */
7156         if (!torture_open_connection(&cli, 0)) {
7157                 goto fail;
7158         }
7159
7160         smbXcli_conn_set_sockopt(cli->conn, sockops);
7161
7162         /* Start with a clean slate. */
7163         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7164
7165         /* Create the test file. */
7166         status = cli_ntcreate(cli,
7167                                 fname,
7168                                 0,
7169                                 GENERIC_ALL_ACCESS,
7170                                 FILE_ATTRIBUTE_NORMAL,
7171                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7172                                         FILE_SHARE_DELETE,
7173                                 FILE_CREATE,
7174                                 0,
7175                                 0,
7176                                 &fnum,
7177                                 NULL);
7178         if (!NT_STATUS_IS_OK(status)) {
7179                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7180                 goto fail;
7181         }
7182
7183         status = cli_close(cli, fnum);
7184
7185         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7186         /*
7187          * On SMB1 this succeeds - SMB2 it fails,
7188          * see the SMB2-SACL test.
7189          */
7190         status = cli_ntcreate(cli,
7191                                 fname,
7192                                 0,
7193                                 SEC_FLAG_SYSTEM_SECURITY,
7194                                 FILE_ATTRIBUTE_NORMAL,
7195                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7196                                         FILE_SHARE_DELETE,
7197                                 FILE_OPEN,
7198                                 0,
7199                                 0,
7200                                 &fnum,
7201                                 NULL);
7202         if (!NT_STATUS_IS_OK(status)) {
7203                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7204                 goto fail;
7205         }
7206
7207         status = cli_close(cli, fnum);
7208
7209         cli_unlink(cli, fname,
7210                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7211
7212         torture_close_connection(cli);
7213         TALLOC_FREE(frame);
7214         return true;
7215
7216   fail:
7217
7218         if (cli) {
7219                 if (fnum != (uint16_t)-1) {
7220                         cli_close(cli, fnum);
7221                 }
7222                 cli_unlink(cli, fname,
7223                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7224                 torture_close_connection(cli);
7225         }
7226
7227         TALLOC_FREE(frame);
7228         return false;
7229 }
7230
7231 static bool run_pipe_number(int dummy)
7232 {
7233         struct cli_state *cli1;
7234         const char *pipe_name = "\\SPOOLSS";
7235         uint16_t fnum;
7236         int num_pipes = 0;
7237         NTSTATUS status;
7238
7239         printf("starting pipenumber test\n");
7240         if (!torture_open_connection(&cli1, 0)) {
7241                 return False;
7242         }
7243
7244         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7245         while(1) {
7246                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7247                                       FILE_ATTRIBUTE_NORMAL,
7248                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7249                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7250                 if (!NT_STATUS_IS_OK(status)) {
7251                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7252                         break;
7253                 }
7254                 num_pipes++;
7255                 printf("\r%6d", num_pipes);
7256         }
7257
7258         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7259         torture_close_connection(cli1);
7260         return True;
7261 }
7262
7263 /*
7264   Test open mode returns on read-only files.
7265  */
7266 static bool run_opentest(int dummy)
7267 {
7268         static struct cli_state *cli1;
7269         static struct cli_state *cli2;
7270         const char *fname = "\\readonly.file";
7271         uint16_t fnum1, fnum2;
7272         char buf[20];
7273         off_t fsize;
7274         bool correct = True;
7275         char *tmp_path;
7276         NTSTATUS status;
7277
7278         printf("starting open test\n");
7279
7280         if (!torture_open_connection(&cli1, 0)) {
7281                 return False;
7282         }
7283
7284         cli_setatr(cli1, fname, 0, 0);
7285         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7286
7287         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7288
7289         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7290         if (!NT_STATUS_IS_OK(status)) {
7291                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7292                 return False;
7293         }
7294
7295         status = cli_close(cli1, fnum1);
7296         if (!NT_STATUS_IS_OK(status)) {
7297                 printf("close2 failed (%s)\n", nt_errstr(status));
7298                 return False;
7299         }
7300
7301         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7302         if (!NT_STATUS_IS_OK(status)) {
7303                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7304                 return False;
7305         }
7306
7307         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7308         if (!NT_STATUS_IS_OK(status)) {
7309                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7310                 return False;
7311         }
7312
7313         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7314         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7315
7316         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7317                         NT_STATUS_ACCESS_DENIED)) {
7318                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7319         }
7320
7321         printf("finished open test 1\n");
7322
7323         cli_close(cli1, fnum1);
7324
7325         /* Now try not readonly and ensure ERRbadshare is returned. */
7326
7327         cli_setatr(cli1, fname, 0, 0);
7328
7329         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7330         if (!NT_STATUS_IS_OK(status)) {
7331                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7332                 return False;
7333         }
7334
7335         /* This will fail - but the error should be ERRshare. */
7336         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7337
7338         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7339                         NT_STATUS_SHARING_VIOLATION)) {
7340                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7341         }
7342
7343         status = cli_close(cli1, fnum1);
7344         if (!NT_STATUS_IS_OK(status)) {
7345                 printf("close2 failed (%s)\n", nt_errstr(status));
7346                 return False;
7347         }
7348
7349         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7350
7351         printf("finished open test 2\n");
7352
7353         /* Test truncate open disposition on file opened for read. */
7354         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7355         if (!NT_STATUS_IS_OK(status)) {
7356                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7357                 return False;
7358         }
7359
7360         /* write 20 bytes. */
7361
7362         memset(buf, '\0', 20);
7363
7364         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7365         if (!NT_STATUS_IS_OK(status)) {
7366                 printf("write failed (%s)\n", nt_errstr(status));
7367                 correct = False;
7368         }
7369
7370         status = cli_close(cli1, fnum1);
7371         if (!NT_STATUS_IS_OK(status)) {
7372                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7373                 return False;
7374         }
7375
7376         /* Ensure size == 20. */
7377         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7378         if (!NT_STATUS_IS_OK(status)) {
7379                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7380                 return False;
7381         }
7382
7383         if (fsize != 20) {
7384                 printf("(3) file size != 20\n");
7385                 return False;
7386         }
7387
7388         /* Now test if we can truncate a file opened for readonly. */
7389         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7390         if (!NT_STATUS_IS_OK(status)) {
7391                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7392                 return False;
7393         }
7394
7395         status = cli_close(cli1, fnum1);
7396         if (!NT_STATUS_IS_OK(status)) {
7397                 printf("close2 failed (%s)\n", nt_errstr(status));
7398                 return False;
7399         }
7400
7401         /* Ensure size == 0. */
7402         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7403         if (!NT_STATUS_IS_OK(status)) {
7404                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7405                 return False;
7406         }
7407
7408         if (fsize != 0) {
7409                 printf("(3) file size != 0\n");
7410                 return False;
7411         }
7412         printf("finished open test 3\n");
7413
7414         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7415
7416         printf("Do ctemp tests\n");
7417         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7418         if (!NT_STATUS_IS_OK(status)) {
7419                 printf("ctemp failed (%s)\n", nt_errstr(status));
7420                 return False;
7421         }
7422
7423         printf("ctemp gave path %s\n", tmp_path);
7424         status = cli_close(cli1, fnum1);
7425         if (!NT_STATUS_IS_OK(status)) {
7426                 printf("close of temp failed (%s)\n", nt_errstr(status));
7427         }
7428
7429         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7430         if (!NT_STATUS_IS_OK(status)) {
7431                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7432         }
7433
7434         /* Test the non-io opens... */
7435
7436         if (!torture_open_connection(&cli2, 1)) {
7437                 return False;
7438         }
7439
7440         cli_setatr(cli2, fname, 0, 0);
7441         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7442
7443         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7444
7445         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7446         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7447                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7448                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7449         if (!NT_STATUS_IS_OK(status)) {
7450                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7451                 return False;
7452         }
7453
7454         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7455                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7456                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7457         if (!NT_STATUS_IS_OK(status)) {
7458                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7459                 return False;
7460         }
7461
7462         status = cli_close(cli1, fnum1);
7463         if (!NT_STATUS_IS_OK(status)) {
7464                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7465                 return False;
7466         }
7467
7468         status = cli_close(cli2, fnum2);
7469         if (!NT_STATUS_IS_OK(status)) {
7470                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7471                 return False;
7472         }
7473
7474         printf("non-io open test #1 passed.\n");
7475
7476         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7477
7478         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7479
7480         status = cli_ntcreate(cli1, fname, 0,
7481                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7482                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7483                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7484         if (!NT_STATUS_IS_OK(status)) {
7485                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7486                 return False;
7487         }
7488
7489         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7490                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7491                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7492         if (!NT_STATUS_IS_OK(status)) {
7493                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7494                 return False;
7495         }
7496
7497         status = cli_close(cli1, fnum1);
7498         if (!NT_STATUS_IS_OK(status)) {
7499                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7500                 return False;
7501         }
7502
7503         status = cli_close(cli2, fnum2);
7504         if (!NT_STATUS_IS_OK(status)) {
7505                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7506                 return False;
7507         }
7508
7509         printf("non-io open test #2 passed.\n");
7510
7511         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7512
7513         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7514
7515         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7516                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7517                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7518         if (!NT_STATUS_IS_OK(status)) {
7519                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7520                 return False;
7521         }
7522
7523         status = cli_ntcreate(cli2, fname, 0,
7524                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7525                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7526                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7527         if (!NT_STATUS_IS_OK(status)) {
7528                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7529                 return False;
7530         }
7531
7532         status = cli_close(cli1, fnum1);
7533         if (!NT_STATUS_IS_OK(status)) {
7534                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7535                 return False;
7536         }
7537
7538         status = cli_close(cli2, fnum2);
7539         if (!NT_STATUS_IS_OK(status)) {
7540                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7541                 return False;
7542         }
7543
7544         printf("non-io open test #3 passed.\n");
7545
7546         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7547
7548         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7549
7550         status = cli_ntcreate(cli1, fname, 0,
7551                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7552                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7553                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7554         if (!NT_STATUS_IS_OK(status)) {
7555                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7556                 return False;
7557         }
7558
7559         status = cli_ntcreate(cli2, fname, 0,
7560                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7561                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7562                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7563         if (NT_STATUS_IS_OK(status)) {
7564                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7565                 return False;
7566         }
7567
7568         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7569
7570         status = cli_close(cli1, fnum1);
7571         if (!NT_STATUS_IS_OK(status)) {
7572                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7573                 return False;
7574         }
7575
7576         printf("non-io open test #4 passed.\n");
7577
7578         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7579
7580         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7581
7582         status = cli_ntcreate(cli1, fname, 0,
7583                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7584                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7585                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7586         if (!NT_STATUS_IS_OK(status)) {
7587                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7588                 return False;
7589         }
7590
7591         status = cli_ntcreate(cli2, fname, 0,
7592                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7593                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7594                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7595         if (!NT_STATUS_IS_OK(status)) {
7596                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7597                 return False;
7598         }
7599
7600         status = cli_close(cli1, fnum1);
7601         if (!NT_STATUS_IS_OK(status)) {
7602                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7603                 return False;
7604         }
7605
7606         status = cli_close(cli2, fnum2);
7607         if (!NT_STATUS_IS_OK(status)) {
7608                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7609                 return False;
7610         }
7611
7612         printf("non-io open test #5 passed.\n");
7613
7614         printf("TEST #6 testing 1 non-io open, one io open\n");
7615
7616         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7617
7618         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7619                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7620                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7621         if (!NT_STATUS_IS_OK(status)) {
7622                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7623                 return False;
7624         }
7625
7626         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7627                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7628                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7629         if (!NT_STATUS_IS_OK(status)) {
7630                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7631                 return False;
7632         }
7633
7634         status = cli_close(cli1, fnum1);
7635         if (!NT_STATUS_IS_OK(status)) {
7636                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7637                 return False;
7638         }
7639
7640         status = cli_close(cli2, fnum2);
7641         if (!NT_STATUS_IS_OK(status)) {
7642                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7643                 return False;
7644         }
7645
7646         printf("non-io open test #6 passed.\n");
7647
7648         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7649
7650         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7651
7652         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7653                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7654                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7655         if (!NT_STATUS_IS_OK(status)) {
7656                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7657                 return False;
7658         }
7659
7660         status = cli_ntcreate(cli2, fname, 0,
7661                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7662                               FILE_ATTRIBUTE_NORMAL,
7663                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7664                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7665         if (NT_STATUS_IS_OK(status)) {
7666                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7667                 return False;
7668         }
7669
7670         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7671
7672         status = cli_close(cli1, fnum1);
7673         if (!NT_STATUS_IS_OK(status)) {
7674                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7675                 return False;
7676         }
7677
7678         printf("non-io open test #7 passed.\n");
7679
7680         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7681
7682         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7683         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7684                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7685                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7686         if (!NT_STATUS_IS_OK(status)) {
7687                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7688                 correct = false;
7689                 goto out;
7690         }
7691
7692         /* Write to ensure we have to update the file time. */
7693         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7694                               NULL);
7695         if (!NT_STATUS_IS_OK(status)) {
7696                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7697                 correct = false;
7698                 goto out;
7699         }
7700
7701         status = cli_close(cli1, fnum1);
7702         if (!NT_STATUS_IS_OK(status)) {
7703                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7704                 correct = false;
7705         }
7706
7707   out:
7708
7709         if (!torture_close_connection(cli1)) {
7710                 correct = False;
7711         }
7712         if (!torture_close_connection(cli2)) {
7713                 correct = False;
7714         }
7715
7716         return correct;
7717 }
7718
7719 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7720 {
7721         uint16_t major, minor;
7722         uint32_t caplow, caphigh;
7723         NTSTATUS status;
7724
7725         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7726                 printf("Server doesn't support UNIX CIFS extensions.\n");
7727                 return NT_STATUS_NOT_SUPPORTED;
7728         }
7729
7730         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7731                                              &caphigh);
7732         if (!NT_STATUS_IS_OK(status)) {
7733                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7734                        nt_errstr(status));
7735                 return status;
7736         }
7737
7738         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7739                                                       caplow, caphigh);
7740         if (!NT_STATUS_IS_OK(status)) {
7741                 printf("Server doesn't support setting UNIX CIFS extensions: "
7742                        "%s.\n", nt_errstr(status));
7743                 return status;
7744         }
7745
7746         return NT_STATUS_OK;
7747 }
7748
7749 /*
7750   Test POSIX open /mkdir calls.
7751  */
7752 static bool run_simple_posix_open_test(int dummy)
7753 {
7754         static struct cli_state *cli1;
7755         const char *fname = "posix:file";
7756         const char *hname = "posix:hlink";
7757         const char *sname = "posix:symlink";
7758         const char *dname = "posix:dir";
7759         char buf[10];
7760         char *target = NULL;
7761         uint16_t fnum1 = (uint16_t)-1;
7762         SMB_STRUCT_STAT sbuf;
7763         bool correct = false;
7764         NTSTATUS status;
7765         size_t nread;
7766         const char *fname_windows = "windows_file";
7767         uint16_t fnum2 = (uint16_t)-1;
7768         bool ok;
7769
7770         printf("Starting simple POSIX open test\n");
7771
7772         if (!torture_open_connection(&cli1, 0)) {
7773                 return false;
7774         }
7775
7776         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7777
7778         status = torture_setup_unix_extensions(cli1);
7779         if (!NT_STATUS_IS_OK(status)) {
7780                 return false;
7781         }
7782
7783         cli_setatr(cli1, fname, 0, 0);
7784         cli_posix_unlink(cli1, fname);
7785         cli_setatr(cli1, dname, 0, 0);
7786         cli_posix_rmdir(cli1, dname);
7787         cli_setatr(cli1, hname, 0, 0);
7788         cli_posix_unlink(cli1, hname);
7789         cli_setatr(cli1, sname, 0, 0);
7790         cli_posix_unlink(cli1, sname);
7791         cli_setatr(cli1, fname_windows, 0, 0);
7792         cli_posix_unlink(cli1, fname_windows);
7793
7794         /* Create a directory. */
7795         status = cli_posix_mkdir(cli1, dname, 0777);
7796         if (!NT_STATUS_IS_OK(status)) {
7797                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7798                 goto out;
7799         }
7800
7801         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7802                                 0600, &fnum1);
7803         if (!NT_STATUS_IS_OK(status)) {
7804                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7805                 goto out;
7806         }
7807
7808         /* Test ftruncate - set file size. */
7809         status = cli_ftruncate(cli1, fnum1, 1000);
7810         if (!NT_STATUS_IS_OK(status)) {
7811                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7812                 goto out;
7813         }
7814
7815         /* Ensure st_size == 1000 */
7816         status = cli_posix_stat(cli1, fname, &sbuf);
7817         if (!NT_STATUS_IS_OK(status)) {
7818                 printf("stat failed (%s)\n", nt_errstr(status));
7819                 goto out;
7820         }
7821
7822         if (sbuf.st_ex_size != 1000) {
7823                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7824                 goto out;
7825         }
7826
7827         /* Ensure st_mode == 0600 */
7828         if ((sbuf.st_ex_mode & 07777) != 0600) {
7829                 printf("posix_open - bad permissions 0%o != 0600\n",
7830                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7831                 goto out;
7832         }
7833
7834         /* Test ftruncate - set file size back to zero. */
7835         status = cli_ftruncate(cli1, fnum1, 0);
7836         if (!NT_STATUS_IS_OK(status)) {
7837                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7838                 goto out;
7839         }
7840
7841         status = cli_close(cli1, fnum1);
7842         if (!NT_STATUS_IS_OK(status)) {
7843                 printf("close failed (%s)\n", nt_errstr(status));
7844                 goto out;
7845         }
7846
7847         /* Now open the file again for read only. */
7848         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7849         if (!NT_STATUS_IS_OK(status)) {
7850                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7851                 goto out;
7852         }
7853
7854         /* Now unlink while open. */
7855         status = cli_posix_unlink(cli1, fname);
7856         if (!NT_STATUS_IS_OK(status)) {
7857                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7858                 goto out;
7859         }
7860
7861         status = cli_close(cli1, fnum1);
7862         if (!NT_STATUS_IS_OK(status)) {
7863                 printf("close(2) failed (%s)\n", nt_errstr(status));
7864                 goto out;
7865         }
7866
7867         /* Ensure the file has gone. */
7868         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7869         if (NT_STATUS_IS_OK(status)) {
7870                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7871                 goto out;
7872         }
7873
7874         /* Create again to test open with O_TRUNC. */
7875         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7876         if (!NT_STATUS_IS_OK(status)) {
7877                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7878                 goto out;
7879         }
7880
7881         /* Test ftruncate - set file size. */
7882         status = cli_ftruncate(cli1, fnum1, 1000);
7883         if (!NT_STATUS_IS_OK(status)) {
7884                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7885                 goto out;
7886         }
7887
7888         /* Ensure st_size == 1000 */
7889         status = cli_posix_stat(cli1, fname, &sbuf);
7890         if (!NT_STATUS_IS_OK(status)) {
7891                 printf("stat failed (%s)\n", nt_errstr(status));
7892                 goto out;
7893         }
7894
7895         if (sbuf.st_ex_size != 1000) {
7896                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7897                 goto out;
7898         }
7899
7900         status = cli_close(cli1, fnum1);
7901         if (!NT_STATUS_IS_OK(status)) {
7902                 printf("close(2) failed (%s)\n", nt_errstr(status));
7903                 goto out;
7904         }
7905
7906         /* Re-open with O_TRUNC. */
7907         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7908         if (!NT_STATUS_IS_OK(status)) {
7909                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7910                 goto out;
7911         }
7912
7913         /* Ensure st_size == 0 */
7914         status = cli_posix_stat(cli1, fname, &sbuf);
7915         if (!NT_STATUS_IS_OK(status)) {
7916                 printf("stat failed (%s)\n", nt_errstr(status));
7917                 goto out;
7918         }
7919
7920         if (sbuf.st_ex_size != 0) {
7921                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7922                 goto out;
7923         }
7924
7925         status = cli_close(cli1, fnum1);
7926         if (!NT_STATUS_IS_OK(status)) {
7927                 printf("close failed (%s)\n", nt_errstr(status));
7928                 goto out;
7929         }
7930
7931         status = cli_posix_unlink(cli1, fname);
7932         if (!NT_STATUS_IS_OK(status)) {
7933                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7934                 goto out;
7935         }
7936
7937         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7938         if (!NT_STATUS_IS_OK(status)) {
7939                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7940                         dname, nt_errstr(status));
7941                 goto out;
7942         }
7943
7944         cli_close(cli1, fnum1);
7945
7946         /* What happens when we try and POSIX open a directory for write ? */
7947         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7948         if (NT_STATUS_IS_OK(status)) {
7949                 printf("POSIX open of directory %s succeeded, "
7950                        "should have failed.\n",
7951                        dname);
7952                 goto out;
7953         } else {
7954                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7955                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7956                         goto out;
7957                 }
7958         }
7959
7960         /* Create the file. */
7961         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7962                                 0600, &fnum1);
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7965                 goto out;
7966         }
7967
7968         /* Write some data into it. */
7969         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7970                               NULL);
7971         if (!NT_STATUS_IS_OK(status)) {
7972                 printf("cli_write failed: %s\n", nt_errstr(status));
7973                 goto out;
7974         }
7975
7976         cli_close(cli1, fnum1);
7977
7978         /* Now create a hardlink. */
7979         status = cli_posix_hardlink(cli1, fname, hname);
7980         if (!NT_STATUS_IS_OK(status)) {
7981                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7982                 goto out;
7983         }
7984
7985         /* Now create a symlink. */
7986         status = cli_posix_symlink(cli1, fname, sname);
7987         if (!NT_STATUS_IS_OK(status)) {
7988                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7989                 goto out;
7990         }
7991
7992         /* Open the hardlink for read. */
7993         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7994         if (!NT_STATUS_IS_OK(status)) {
7995                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7996                 goto out;
7997         }
7998
7999         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8000         if (!NT_STATUS_IS_OK(status)) {
8001                 printf("POSIX read of %s failed (%s)\n", hname,
8002                        nt_errstr(status));
8003                 goto out;
8004         } else if (nread != 10) {
8005                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8006                        hname, (unsigned long)nread, 10);
8007                 goto out;
8008         }
8009
8010         if (memcmp(buf, "TEST DATA\n", 10)) {
8011                 printf("invalid data read from hardlink\n");
8012                 goto out;
8013         }
8014
8015         /* Do a POSIX lock/unlock. */
8016         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8017         if (!NT_STATUS_IS_OK(status)) {
8018                 printf("POSIX lock failed %s\n", nt_errstr(status));
8019                 goto out;
8020         }
8021
8022         /* Punch a hole in the locked area. */
8023         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8024         if (!NT_STATUS_IS_OK(status)) {
8025                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8026                 goto out;
8027         }
8028
8029         cli_close(cli1, fnum1);
8030
8031         /* Open the symlink for read - this should fail. A POSIX
8032            client should not be doing opens on a symlink. */
8033         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8034         if (NT_STATUS_IS_OK(status)) {
8035                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8036                 goto out;
8037         }
8038         ok = check_both_error(
8039                 __LINE__, status, ERRDOS, ERRbadpath,
8040                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8041         if (!ok) {
8042                 printf("POSIX open of %s should have failed "
8043                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8044                        "failed with %s instead.\n",
8045                        sname, nt_errstr(status));
8046                 goto out;
8047         }
8048
8049         status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
8050         if (!NT_STATUS_IS_OK(status)) {
8051                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8052                 goto out;
8053         }
8054
8055         if (strcmp(target, fname) != 0) {
8056                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8057                         sname, fname, target);
8058                 goto out;
8059         }
8060
8061         status = cli_posix_rmdir(cli1, dname);
8062         if (!NT_STATUS_IS_OK(status)) {
8063                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8064                 goto out;
8065         }
8066
8067         /* Check directory opens with a specific permission. */
8068         status = cli_posix_mkdir(cli1, dname, 0700);
8069         if (!NT_STATUS_IS_OK(status)) {
8070                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8071                 goto out;
8072         }
8073
8074         /* Ensure st_mode == 0700 */
8075         status = cli_posix_stat(cli1, dname, &sbuf);
8076         if (!NT_STATUS_IS_OK(status)) {
8077                 printf("stat failed (%s)\n", nt_errstr(status));
8078                 goto out;
8079         }
8080
8081         if ((sbuf.st_ex_mode & 07777) != 0700) {
8082                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8083                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8084                 goto out;
8085         }
8086
8087         /*
8088          * Now create a Windows file, and attempt a POSIX unlink.
8089          * This should fail with a sharing violation but due to:
8090          *
8091          * [Bug 9571] Unlink after open causes smbd to panic
8092          *
8093          * ensure we've fixed the lock ordering violation.
8094          */
8095
8096         status = cli_ntcreate(cli1, fname_windows, 0,
8097                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8098                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8099                         FILE_CREATE,
8100                         0x0, 0x0, &fnum2, NULL);
8101         if (!NT_STATUS_IS_OK(status)) {
8102                 printf("Windows create of %s failed (%s)\n", fname_windows,
8103                         nt_errstr(status));
8104                 goto out;
8105         }
8106
8107         /* Now try posix_unlink. */
8108         status = cli_posix_unlink(cli1, fname_windows);
8109         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8110                 printf("POSIX unlink of %s should fail "
8111                         "with NT_STATUS_SHARING_VIOLATION "
8112                         "got %s instead !\n",
8113                         fname_windows,
8114                         nt_errstr(status));
8115                 goto out;
8116         }
8117
8118         cli_close(cli1, fnum2);
8119
8120         printf("Simple POSIX open test passed\n");
8121         correct = true;
8122
8123   out:
8124
8125         if (fnum1 != (uint16_t)-1) {
8126                 cli_close(cli1, fnum1);
8127                 fnum1 = (uint16_t)-1;
8128         }
8129
8130         if (fnum2 != (uint16_t)-1) {
8131                 cli_close(cli1, fnum2);
8132                 fnum2 = (uint16_t)-1;
8133         }
8134
8135         cli_setatr(cli1, sname, 0, 0);
8136         cli_posix_unlink(cli1, sname);
8137         cli_setatr(cli1, hname, 0, 0);
8138         cli_posix_unlink(cli1, hname);
8139         cli_setatr(cli1, fname, 0, 0);
8140         cli_posix_unlink(cli1, fname);
8141         cli_setatr(cli1, dname, 0, 0);
8142         cli_posix_rmdir(cli1, dname);
8143         cli_setatr(cli1, fname_windows, 0, 0);
8144         cli_posix_unlink(cli1, fname_windows);
8145
8146         if (!torture_close_connection(cli1)) {
8147                 correct = false;
8148         }
8149
8150         return correct;
8151 }
8152
8153 /*
8154   Test POSIX and Windows ACLs are rejected on symlinks.
8155  */
8156 static bool run_acl_symlink_test(int dummy)
8157 {
8158         static struct cli_state *cli;
8159         const char *fname = "posix_file";
8160         const char *sname = "posix_symlink";
8161         uint16_t fnum = (uint16_t)-1;
8162         bool correct = false;
8163         NTSTATUS status;
8164         char *posix_acl = NULL;
8165         size_t posix_acl_len = 0;
8166         char *posix_acl_sym = NULL;
8167         size_t posix_acl_len_sym = 0;
8168         struct security_descriptor *sd = NULL;
8169         TALLOC_CTX *frame = NULL;
8170
8171         frame = talloc_stackframe();
8172
8173         printf("Starting acl symlink test\n");
8174
8175         if (!torture_open_connection(&cli, 0)) {
8176                 TALLOC_FREE(frame);
8177                 return false;
8178         }
8179
8180         smbXcli_conn_set_sockopt(cli->conn, sockops);
8181
8182         status = torture_setup_unix_extensions(cli);
8183         if (!NT_STATUS_IS_OK(status)) {
8184                 TALLOC_FREE(frame);
8185                 return false;
8186         }
8187
8188         cli_setatr(cli, fname, 0, 0);
8189         cli_posix_unlink(cli, fname);
8190         cli_setatr(cli, sname, 0, 0);
8191         cli_posix_unlink(cli, sname);
8192
8193         status = cli_ntcreate(cli,
8194                         fname,
8195                         0,
8196                         READ_CONTROL_ACCESS,
8197                         0,
8198                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8199                         FILE_CREATE,
8200                         0x0,
8201                         0x0,
8202                         &fnum,
8203                         NULL);
8204
8205         if (!NT_STATUS_IS_OK(status)) {
8206                 printf("cli_ntcreate of %s failed (%s)\n",
8207                         fname,
8208                         nt_errstr(status));
8209                 goto out;
8210         }
8211
8212         /* Get the Windows ACL on the file. */
8213         status = cli_query_secdesc(cli,
8214                                 fnum,
8215                                 frame,
8216                                 &sd);
8217         if (!NT_STATUS_IS_OK(status)) {
8218                 printf("cli_query_secdesc failed (%s)\n",
8219                         nt_errstr(status));
8220                 goto out;
8221         }
8222
8223         /* Get the POSIX ACL on the file. */
8224         status = cli_posix_getacl(cli,
8225                                 fname,
8226                                 frame,
8227                                 &posix_acl_len,
8228                                 &posix_acl);
8229
8230         if (!NT_STATUS_IS_OK(status)) {
8231                 printf("cli_posix_getacl failed (%s)\n",
8232                         nt_errstr(status));
8233                 goto out;
8234         }
8235
8236         status = cli_close(cli, fnum);
8237         if (!NT_STATUS_IS_OK(status)) {
8238                 printf("close failed (%s)\n", nt_errstr(status));
8239                 goto out;
8240         }
8241         fnum = (uint16_t)-1;
8242
8243         /* Now create a symlink. */
8244         status = cli_posix_symlink(cli, fname, sname);
8245         if (!NT_STATUS_IS_OK(status)) {
8246                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8247                         sname,
8248                         fname,
8249                         nt_errstr(status));
8250                 goto out;
8251         }
8252
8253         /* Open a handle on the symlink for SD set/get should fail. */
8254         status = cli_ntcreate(cli,
8255                         sname,
8256                         0,
8257                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8258                         0,
8259                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8260                         FILE_OPEN,
8261                         0x0,
8262                         0x0,
8263                         &fnum,
8264                         NULL);
8265
8266         if (NT_STATUS_IS_OK(status)) {
8267                 printf("Symlink open for getsd/setsd of %s "
8268                         "succeeded (should fail)\n",
8269                         sname);
8270                 goto out;
8271         }
8272
8273         /* Try a stat-open on the symlink, should also fail. */
8274         status = cli_ntcreate(cli,
8275                         sname,
8276                         0,
8277                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8278                         0,
8279                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8280                         FILE_OPEN,
8281                         0x0,
8282                         0x0,
8283                         &fnum,
8284                         NULL);
8285
8286         if (NT_STATUS_IS_OK(status)) {
8287                 printf("Stat-open of symlink succeeded (should fail)\n");
8288                 goto out;
8289         }
8290
8291         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8292         status = cli_posix_getacl(cli,
8293                                 sname,
8294                                 frame,
8295                                 &posix_acl_len_sym,
8296                                 &posix_acl_sym);
8297
8298         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8299                 printf("cli_posix_getacl on a symlink gave %s. "
8300                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8301                         nt_errstr(status));
8302                 goto out;
8303         }
8304
8305         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8306         status = cli_posix_setacl(cli,
8307                                 sname,
8308                                 posix_acl,
8309                                 posix_acl_len);
8310
8311         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8312                 printf("cli_posix_setacl on a symlink gave %s. "
8313                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8314                         nt_errstr(status));
8315                 goto out;
8316         }
8317
8318         printf("ACL symlink test passed\n");
8319         correct = true;
8320
8321   out:
8322
8323         if (fnum != (uint16_t)-1) {
8324                 cli_close(cli, fnum);
8325                 fnum = (uint16_t)-1;
8326         }
8327
8328         cli_setatr(cli, sname, 0, 0);
8329         cli_posix_unlink(cli, sname);
8330         cli_setatr(cli, fname, 0, 0);
8331         cli_posix_unlink(cli, fname);
8332
8333         if (!torture_close_connection(cli)) {
8334                 correct = false;
8335         }
8336
8337         TALLOC_FREE(frame);
8338         return correct;
8339 }
8340
8341 /*
8342   Test POSIX can delete a file containing streams.
8343  */
8344 static bool run_posix_stream_delete(int dummy)
8345 {
8346         struct cli_state *cli1 = NULL;
8347         struct cli_state *cli2 = NULL;
8348         const char *fname = "streamfile";
8349         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8350         uint16_t fnum1 = (uint16_t)-1;
8351         bool correct = false;
8352         NTSTATUS status;
8353         TALLOC_CTX *frame = NULL;
8354
8355         frame = talloc_stackframe();
8356
8357         printf("Starting POSIX stream delete test\n");
8358
8359         if (!torture_open_connection(&cli1, 0) ||
8360                         !torture_open_connection(&cli2, 1)) {
8361                 TALLOC_FREE(frame);
8362                 return false;
8363         }
8364
8365         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8366         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8367
8368         status = torture_setup_unix_extensions(cli2);
8369         if (!NT_STATUS_IS_OK(status)) {
8370                 goto out;
8371         }
8372
8373         cli_setatr(cli1, fname, 0, 0);
8374         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8375
8376         /* Create the file. */
8377         status = cli_ntcreate(cli1,
8378                         fname,
8379                         0,
8380                         READ_CONTROL_ACCESS,
8381                         0,
8382                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8383                         FILE_CREATE,
8384                         0x0,
8385                         0x0,
8386                         &fnum1,
8387                         NULL);
8388
8389         if (!NT_STATUS_IS_OK(status)) {
8390                 printf("cli_ntcreate of %s failed (%s)\n",
8391                         fname,
8392                         nt_errstr(status));
8393                 goto out;
8394         }
8395
8396         status = cli_close(cli1, fnum1);
8397         if (!NT_STATUS_IS_OK(status)) {
8398                 printf("cli_close of %s failed (%s)\n",
8399                         fname,
8400                         nt_errstr(status));
8401                 goto out;
8402         }
8403         fnum1 = (uint16_t)-1;
8404
8405         /* Now create the stream. */
8406         status = cli_ntcreate(cli1,
8407                         stream_fname,
8408                         0,
8409                         FILE_WRITE_DATA,
8410                         0,
8411                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8412                         FILE_CREATE,
8413                         0x0,
8414                         0x0,
8415                         &fnum1,
8416                         NULL);
8417
8418         if (!NT_STATUS_IS_OK(status)) {
8419                 printf("cli_ntcreate of %s failed (%s)\n",
8420                         stream_fname,
8421                         nt_errstr(status));
8422                 goto out;
8423         }
8424
8425         /* Leave the stream handle open... */
8426
8427         /* POSIX unlink should fail. */
8428         status = cli_posix_unlink(cli2, fname);
8429         if (NT_STATUS_IS_OK(status)) {
8430                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8431                         fname);
8432                 goto out;
8433         }
8434
8435         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8436                 printf("cli_posix_unlink of %s failed with (%s) "
8437                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8438                         fname,
8439                         nt_errstr(status));
8440                 goto out;
8441         }
8442
8443         /* Close the stream handle. */
8444         status = cli_close(cli1, fnum1);
8445         if (!NT_STATUS_IS_OK(status)) {
8446                 printf("cli_close of %s failed (%s)\n",
8447                         stream_fname,
8448                         nt_errstr(status));
8449                 goto out;
8450         }
8451         fnum1 = (uint16_t)-1;
8452
8453         /* POSIX unlink after stream handle closed should succeed. */
8454         status = cli_posix_unlink(cli2, fname);
8455         if (!NT_STATUS_IS_OK(status)) {
8456                 printf("cli_posix_unlink of %s failed (%s)\n",
8457                         fname,
8458                         nt_errstr(status));
8459                 goto out;
8460         }
8461
8462         printf("POSIX stream delete test passed\n");
8463         correct = true;
8464
8465   out:
8466
8467         if (fnum1 != (uint16_t)-1) {
8468                 cli_close(cli1, fnum1);
8469                 fnum1 = (uint16_t)-1;
8470         }
8471
8472         cli_setatr(cli1, fname, 0, 0);
8473         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8474
8475         if (!torture_close_connection(cli1)) {
8476                 correct = false;
8477         }
8478         if (!torture_close_connection(cli2)) {
8479                 correct = false;
8480         }
8481
8482         TALLOC_FREE(frame);
8483         return correct;
8484 }
8485
8486 /*
8487   Test setting EA's are rejected on symlinks.
8488  */
8489 static bool run_ea_symlink_test(int dummy)
8490 {
8491         static struct cli_state *cli;
8492         const char *fname = "posix_file_ea";
8493         const char *sname = "posix_symlink_ea";
8494         const char *ea_name = "testea_name";
8495         const char *ea_value = "testea_value";
8496         uint16_t fnum = (uint16_t)-1;
8497         bool correct = false;
8498         NTSTATUS status;
8499         size_t i, num_eas;
8500         struct ea_struct *eas = NULL;
8501         TALLOC_CTX *frame = NULL;
8502
8503         frame = talloc_stackframe();
8504
8505         printf("Starting EA symlink test\n");
8506
8507         if (!torture_open_connection(&cli, 0)) {
8508                 TALLOC_FREE(frame);
8509                 return false;
8510         }
8511
8512         smbXcli_conn_set_sockopt(cli->conn, sockops);
8513
8514         status = torture_setup_unix_extensions(cli);
8515         if (!NT_STATUS_IS_OK(status)) {
8516                 TALLOC_FREE(frame);
8517                 return false;
8518         }
8519
8520         cli_setatr(cli, fname, 0, 0);
8521         cli_posix_unlink(cli, fname);
8522         cli_setatr(cli, sname, 0, 0);
8523         cli_posix_unlink(cli, sname);
8524
8525         status = cli_ntcreate(cli,
8526                         fname,
8527                         0,
8528                         READ_CONTROL_ACCESS,
8529                         0,
8530                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8531                         FILE_CREATE,
8532                         0x0,
8533                         0x0,
8534                         &fnum,
8535                         NULL);
8536
8537         if (!NT_STATUS_IS_OK(status)) {
8538                 printf("cli_ntcreate of %s failed (%s)\n",
8539                         fname,
8540                         nt_errstr(status));
8541                 goto out;
8542         }
8543
8544         status = cli_close(cli, fnum);
8545         if (!NT_STATUS_IS_OK(status)) {
8546                 printf("close failed (%s)\n",
8547                         nt_errstr(status));
8548                 goto out;
8549         }
8550         fnum = (uint16_t)-1;
8551
8552         /* Set an EA on the path. */
8553         status = cli_set_ea_path(cli,
8554                                 fname,
8555                                 ea_name,
8556                                 ea_value,
8557                                 strlen(ea_value)+1);
8558
8559         if (!NT_STATUS_IS_OK(status)) {
8560                 printf("cli_set_ea_path failed (%s)\n",
8561                         nt_errstr(status));
8562                 goto out;
8563         }
8564
8565         /* Now create a symlink. */
8566         status = cli_posix_symlink(cli, fname, sname);
8567         if (!NT_STATUS_IS_OK(status)) {
8568                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8569                         sname,
8570                         fname,
8571                         nt_errstr(status));
8572                 goto out;
8573         }
8574
8575         /* Get the EA list on the path. Should return value set. */
8576         status = cli_get_ea_list_path(cli,
8577                                 fname,
8578                                 frame,
8579                                 &num_eas,
8580                                 &eas);
8581
8582         if (!NT_STATUS_IS_OK(status)) {
8583                 printf("cli_get_ea_list_path failed (%s)\n",
8584                         nt_errstr(status));
8585                 goto out;
8586         }
8587
8588         /* Ensure the EA we set is there. */
8589         for (i=0; i<num_eas; i++) {
8590                 if (strcmp(eas[i].name, ea_name) == 0 &&
8591                                 eas[i].value.length == strlen(ea_value)+1 &&
8592                                 memcmp(eas[i].value.data,
8593                                         ea_value,
8594                                         eas[i].value.length) == 0) {
8595                         break;
8596                 }
8597         }
8598
8599         if (i == num_eas) {
8600                 printf("Didn't find EA on pathname %s\n",
8601                         fname);
8602                 goto out;
8603         }
8604
8605         num_eas = 0;
8606         TALLOC_FREE(eas);
8607
8608         /* Get the EA list on the symlink. Should return empty list. */
8609         status = cli_get_ea_list_path(cli,
8610                                 sname,
8611                                 frame,
8612                                 &num_eas,
8613                                 &eas);
8614
8615         if (!NT_STATUS_IS_OK(status)) {
8616                 printf("cli_get_ea_list_path failed (%s)\n",
8617                         nt_errstr(status));
8618                 goto out;
8619         }
8620
8621         if (num_eas != 0) {
8622                 printf("cli_get_ea_list_path failed (%s)\n",
8623                         nt_errstr(status));
8624                 goto out;
8625         }
8626
8627         /* Set an EA on the symlink. Should fail. */
8628         status = cli_set_ea_path(cli,
8629                                 sname,
8630                                 ea_name,
8631                                 ea_value,
8632                                 strlen(ea_value)+1);
8633
8634         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8635                 printf("cli_set_ea_path on a symlink gave %s. "
8636                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8637                         nt_errstr(status));
8638                 goto out;
8639         }
8640
8641         printf("EA symlink test passed\n");
8642         correct = true;
8643
8644   out:
8645
8646         if (fnum != (uint16_t)-1) {
8647                 cli_close(cli, fnum);
8648                 fnum = (uint16_t)-1;
8649         }
8650
8651         cli_setatr(cli, sname, 0, 0);
8652         cli_posix_unlink(cli, sname);
8653         cli_setatr(cli, fname, 0, 0);
8654         cli_posix_unlink(cli, fname);
8655
8656         if (!torture_close_connection(cli)) {
8657                 correct = false;
8658         }
8659
8660         TALLOC_FREE(frame);
8661         return correct;
8662 }
8663
8664 /*
8665   Test POSIX locks are OFD-locks.
8666  */
8667 static bool run_posix_ofd_lock_test(int dummy)
8668 {
8669         static struct cli_state *cli;
8670         const char *fname = "posix_file";
8671         uint16_t fnum1 = (uint16_t)-1;
8672         uint16_t fnum2 = (uint16_t)-1;
8673         bool correct = false;
8674         NTSTATUS status;
8675         TALLOC_CTX *frame = NULL;
8676
8677         frame = talloc_stackframe();
8678
8679         printf("Starting POSIX ofd-lock test\n");
8680
8681         if (!torture_open_connection(&cli, 0)) {
8682                 TALLOC_FREE(frame);
8683                 return false;
8684         }
8685
8686         smbXcli_conn_set_sockopt(cli->conn, sockops);
8687
8688         status = torture_setup_unix_extensions(cli);
8689         if (!NT_STATUS_IS_OK(status)) {
8690                 TALLOC_FREE(frame);
8691                 return false;
8692         }
8693
8694         cli_setatr(cli, fname, 0, 0);
8695         cli_posix_unlink(cli, fname);
8696
8697         /* Open the file twice. */
8698         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8699                                 0600, &fnum1);
8700         if (!NT_STATUS_IS_OK(status)) {
8701                 printf("First POSIX open of %s failed\n", fname);
8702                 goto out;
8703         }
8704
8705         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8706         if (!NT_STATUS_IS_OK(status)) {
8707                 printf("First POSIX open of %s failed\n", fname);
8708                 goto out;
8709         }
8710
8711         /* Set a 0-50 lock on fnum1. */
8712         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8713         if (!NT_STATUS_IS_OK(status)) {
8714                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8715                 goto out;
8716         }
8717
8718         /* Set a 60-100 lock on fnum2. */
8719         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8720         if (!NT_STATUS_IS_OK(status)) {
8721                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8722                 goto out;
8723         }
8724
8725         /* close fnum1 - 0-50 lock should go away. */
8726         status = cli_close(cli, fnum1);
8727         if (!NT_STATUS_IS_OK(status)) {
8728                 printf("close failed (%s)\n",
8729                         nt_errstr(status));
8730                 goto out;
8731         }
8732         fnum1 = (uint16_t)-1;
8733
8734         /* Change the lock context. */
8735         cli_setpid(cli, cli_getpid(cli) + 1);
8736
8737         /* Re-open fnum1. */
8738         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8739         if (!NT_STATUS_IS_OK(status)) {
8740                 printf("Third POSIX open of %s failed\n", fname);
8741                 goto out;
8742         }
8743
8744         /* 60-100 lock should still be there. */
8745         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8746         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8747                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8748                 goto out;
8749         }
8750
8751         /* 0-50 lock should be gone. */
8752         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8753         if (!NT_STATUS_IS_OK(status)) {
8754                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8755                 goto out;
8756         }
8757
8758         printf("POSIX OFD lock test passed\n");
8759         correct = true;
8760
8761   out:
8762
8763         if (fnum1 != (uint16_t)-1) {
8764                 cli_close(cli, fnum1);
8765                 fnum1 = (uint16_t)-1;
8766         }
8767         if (fnum2 != (uint16_t)-1) {
8768                 cli_close(cli, fnum2);
8769                 fnum2 = (uint16_t)-1;
8770         }
8771
8772         cli_setatr(cli, fname, 0, 0);
8773         cli_posix_unlink(cli, fname);
8774
8775         if (!torture_close_connection(cli)) {
8776                 correct = false;
8777         }
8778
8779         TALLOC_FREE(frame);
8780         return correct;
8781 }
8782
8783 struct posix_blocking_state {
8784         struct tevent_context *ev;
8785         struct cli_state *cli1;
8786         uint16_t fnum1;
8787         struct cli_state *cli2;
8788         uint16_t fnum2;
8789         bool gotblocked;
8790         bool gotecho;
8791 };
8792
8793 static void posix_blocking_locked(struct tevent_req *subreq);
8794 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8795 static void posix_blocking_gotecho(struct tevent_req *subreq);
8796 static void posix_blocking_unlocked(struct tevent_req *subreq);
8797
8798 static struct tevent_req *posix_blocking_send(
8799         TALLOC_CTX *mem_ctx,
8800         struct tevent_context *ev,
8801         struct cli_state *cli1,
8802         uint16_t fnum1,
8803         struct cli_state *cli2,
8804         uint16_t fnum2)
8805 {
8806         struct tevent_req *req = NULL, *subreq = NULL;
8807         struct posix_blocking_state *state = NULL;
8808
8809         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8810         if (req == NULL) {
8811                 return NULL;
8812         }
8813         state->ev = ev;
8814         state->cli1 = cli1;
8815         state->fnum1 = fnum1;
8816         state->cli2 = cli2;
8817         state->fnum2 = fnum2;
8818
8819         subreq = cli_posix_lock_send(
8820                 state,
8821                 state->ev,
8822                 state->cli1,
8823                 state->fnum1,
8824                 0,
8825                 1,
8826                 false,
8827                 WRITE_LOCK);
8828         if (tevent_req_nomem(subreq, req)) {
8829                 return tevent_req_post(req, ev);
8830         }
8831         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8832         return req;
8833 }
8834
8835 static void posix_blocking_locked(struct tevent_req *subreq)
8836 {
8837         struct tevent_req *req = tevent_req_callback_data(
8838                 subreq, struct tevent_req);
8839         struct posix_blocking_state *state = tevent_req_data(
8840                 req, struct posix_blocking_state);
8841         NTSTATUS status;
8842
8843         status = cli_posix_lock_recv(subreq);
8844         TALLOC_FREE(subreq);
8845         if (tevent_req_nterror(req, status)) {
8846                 return;
8847         }
8848
8849         subreq = cli_posix_lock_send(
8850                 state,
8851                 state->ev,
8852                 state->cli2,
8853                 state->fnum2,
8854                 0,
8855                 1,
8856                 true,
8857                 WRITE_LOCK);
8858         if (tevent_req_nomem(subreq, req)) {
8859                 return;
8860         }
8861         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8862
8863         /* Make sure the blocking request is delivered */
8864         subreq = cli_echo_send(
8865                 state,
8866                 state->ev,
8867                 state->cli2,
8868                 1,
8869                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8870         if (tevent_req_nomem(subreq, req)) {
8871                 return;
8872         }
8873         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8874 }
8875
8876 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8877 {
8878         struct tevent_req *req = tevent_req_callback_data(
8879                 subreq, struct tevent_req);
8880         struct posix_blocking_state *state = tevent_req_data(
8881                 req, struct posix_blocking_state);
8882         NTSTATUS status;
8883
8884         status = cli_posix_lock_recv(subreq);
8885         TALLOC_FREE(subreq);
8886         if (tevent_req_nterror(req, status)) {
8887                 return;
8888         }
8889         if (!state->gotecho) {
8890                 printf("blocked req got through before echo\n");
8891                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8892                 return;
8893         }
8894         tevent_req_done(req);
8895 }
8896
8897 static void posix_blocking_gotecho(struct tevent_req *subreq)
8898 {
8899         struct tevent_req *req = tevent_req_callback_data(
8900                 subreq, struct tevent_req);
8901         struct posix_blocking_state *state = tevent_req_data(
8902                 req, struct posix_blocking_state);
8903         NTSTATUS status;
8904
8905         status = cli_echo_recv(subreq);
8906         TALLOC_FREE(subreq);
8907         if (tevent_req_nterror(req, status)) {
8908                 return;
8909         }
8910         if (state->gotblocked) {
8911                 printf("blocked req got through before echo\n");
8912                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8913                 return;
8914         }
8915         state->gotecho = true;
8916
8917         subreq = cli_posix_lock_send(
8918                 state,
8919                 state->ev,
8920                 state->cli1,
8921                 state->fnum1,
8922                 0,
8923                 1,
8924                 false,
8925                 UNLOCK_LOCK);
8926         if (tevent_req_nomem(subreq, req)) {
8927                 return;
8928         }
8929         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8930 }
8931
8932 static void posix_blocking_unlocked(struct tevent_req *subreq)
8933 {
8934         struct tevent_req *req = tevent_req_callback_data(
8935                 subreq, struct tevent_req);
8936         NTSTATUS status;
8937
8938         status = cli_posix_lock_recv(subreq);
8939         TALLOC_FREE(subreq);
8940         if (tevent_req_nterror(req, status)) {
8941                 return;
8942         }
8943         /* tevent_req_done in posix_blocking_gotlocked */
8944 }
8945
8946 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8947 {
8948         return tevent_req_simple_recv_ntstatus(req);
8949 }
8950
8951 static bool run_posix_blocking_lock(int dummy)
8952 {
8953         struct tevent_context *ev = NULL;
8954         struct cli_state *cli1 = NULL, *cli2 = NULL;
8955         const char *fname = "posix_blocking";
8956         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8957         struct tevent_req *req = NULL;
8958         NTSTATUS status;
8959         bool ret = false;
8960         bool ok;
8961
8962         printf("Starting posix blocking lock test\n");
8963
8964         ev = samba_tevent_context_init(NULL);
8965         if (ev == NULL) {
8966                 return false;
8967         }
8968
8969         ok = torture_open_connection(&cli1, 0);
8970         if (!ok) {
8971                 goto fail;
8972         }
8973         ok = torture_open_connection(&cli2, 0);
8974         if (!ok) {
8975                 goto fail;
8976         }
8977
8978         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8979
8980         status = torture_setup_unix_extensions(cli1);
8981         if (!NT_STATUS_IS_OK(status)) {
8982                 return false;
8983         }
8984
8985         status = torture_setup_unix_extensions(cli2);
8986         if (!NT_STATUS_IS_OK(status)) {
8987                 return false;
8988         }
8989
8990         cli_setatr(cli1, fname, 0, 0);
8991         cli_posix_unlink(cli1, fname);
8992
8993         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8994                                 0600, &fnum1);
8995         if (!NT_STATUS_IS_OK(status)) {
8996                 printf("First POSIX open of %s failed: %s\n",
8997                        fname,
8998                        nt_errstr(status));
8999                 goto fail;
9000         }
9001
9002         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9003         if (!NT_STATUS_IS_OK(status)) {
9004                 printf("Second POSIX open of %s failed: %s\n",
9005                        fname,
9006                        nt_errstr(status));
9007                 goto fail;
9008         }
9009
9010         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9011         if (req == NULL) {
9012                 printf("cli_posix_blocking failed\n");
9013                 goto fail;
9014         }
9015
9016         ok = tevent_req_poll_ntstatus(req, ev, &status);
9017         if (!ok) {
9018                 printf("tevent_req_poll_ntstatus failed: %s\n",
9019                        nt_errstr(status));
9020                 goto fail;
9021         }
9022         status = posix_blocking_recv(req);
9023         TALLOC_FREE(req);
9024         if (!NT_STATUS_IS_OK(status)) {
9025                 printf("posix_blocking_recv returned %s\n",
9026                        nt_errstr(status));
9027                 goto fail;
9028         }
9029
9030         ret = true;
9031 fail:
9032
9033         if (fnum1 != UINT16_MAX) {
9034                 cli_close(cli1, fnum1);
9035                 fnum1 = UINT16_MAX;
9036         }
9037         if (fnum2 != UINT16_MAX) {
9038                 cli_close(cli2, fnum2);
9039                 fnum2 = UINT16_MAX;
9040         }
9041
9042         if (cli1 != NULL) {
9043                 cli_setatr(cli1, fname, 0, 0);
9044                 cli_posix_unlink(cli1, fname);
9045         }
9046
9047         ok = true;
9048
9049         if (cli1 != NULL) {
9050                 ok &= torture_close_connection(cli1);
9051                 cli1 = NULL;
9052         }
9053         if (cli2 != NULL) {
9054                 ok &= torture_close_connection(cli2);
9055                 cli2 = NULL;
9056         }
9057
9058         if (!ok) {
9059                 ret = false;
9060         }
9061         TALLOC_FREE(ev);
9062         return ret;
9063 }
9064
9065 /*
9066   Test POSIX mkdir is case-sensitive.
9067  */
9068 static bool run_posix_mkdir_test(int dummy)
9069 {
9070         static struct cli_state *cli;
9071         const char *fname_foo = "POSIX_foo";
9072         const char *fname_foo_Foo = "POSIX_foo/Foo";
9073         const char *fname_foo_foo = "POSIX_foo/foo";
9074         const char *fname_Foo = "POSIX_Foo";
9075         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9076         const char *fname_Foo_foo = "POSIX_Foo/foo";
9077         bool correct = false;
9078         NTSTATUS status;
9079         TALLOC_CTX *frame = NULL;
9080         uint16_t fnum = (uint16_t)-1;
9081
9082         frame = talloc_stackframe();
9083
9084         printf("Starting POSIX mkdir test\n");
9085
9086         if (!torture_open_connection(&cli, 0)) {
9087                 TALLOC_FREE(frame);
9088                 return false;
9089         }
9090
9091         smbXcli_conn_set_sockopt(cli->conn, sockops);
9092
9093         status = torture_setup_unix_extensions(cli);
9094         if (!NT_STATUS_IS_OK(status)) {
9095                 TALLOC_FREE(frame);
9096                 return false;
9097         }
9098
9099         cli_posix_rmdir(cli, fname_foo_foo);
9100         cli_posix_rmdir(cli, fname_foo_Foo);
9101         cli_posix_rmdir(cli, fname_foo);
9102
9103         cli_posix_rmdir(cli, fname_Foo_foo);
9104         cli_posix_rmdir(cli, fname_Foo_Foo);
9105         cli_posix_rmdir(cli, fname_Foo);
9106
9107         /*
9108          * Create a file POSIX_foo then try
9109          * and use it in a directory path by
9110          * doing mkdir POSIX_foo/bar.
9111          * The mkdir should fail with
9112          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9113          */
9114
9115         status = cli_posix_open(cli,
9116                         fname_foo,
9117                         O_RDWR|O_CREAT,
9118                         0666,
9119                         &fnum);
9120         if (!NT_STATUS_IS_OK(status)) {
9121                 printf("cli_posix_open of %s failed error %s\n",
9122                         fname_foo,
9123                         nt_errstr(status));
9124                 goto out;
9125         }
9126
9127         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9128         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9129                 printf("cli_posix_mkdir of %s should fail with "
9130                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9131                         "%s instead\n",
9132                         fname_foo_foo,
9133                         nt_errstr(status));
9134                 goto out;
9135         }
9136
9137         status = cli_close(cli, fnum);
9138         if (!NT_STATUS_IS_OK(status)) {
9139                 printf("cli_close failed %s\n", nt_errstr(status));
9140                 goto out;
9141         }
9142         fnum = (uint16_t)-1;
9143
9144         status = cli_posix_unlink(cli, fname_foo);
9145         if (!NT_STATUS_IS_OK(status)) {
9146                 printf("cli_posix_unlink of %s failed error %s\n",
9147                         fname_foo,
9148                         nt_errstr(status));
9149                 goto out;
9150         }
9151
9152         /*
9153          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9154          * posix_open, posix_unlink, on
9155          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9156          * not silently create POSIX_foo/foo.
9157          */
9158
9159         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9160         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9161                 printf("cli_posix_mkdir of %s should fail with "
9162                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9163                         "%s instead\n",
9164                         fname_foo_foo,
9165                         nt_errstr(status));
9166                 goto out;
9167         }
9168
9169         status = cli_posix_rmdir(cli, fname_foo_foo);
9170         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9171                 printf("cli_posix_rmdir of %s should fail with "
9172                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9173                         "%s instead\n",
9174                         fname_foo_foo,
9175                         nt_errstr(status));
9176                 goto out;
9177         }
9178
9179         status = cli_posix_open(cli,
9180                         fname_foo_foo,
9181                         O_RDWR|O_CREAT,
9182                         0666,
9183                         &fnum);
9184         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9185                 printf("cli_posix_open of %s should fail with "
9186                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9187                         "%s instead\n",
9188                         fname_foo_foo,
9189                         nt_errstr(status));
9190                 goto out;
9191         }
9192
9193         status = cli_posix_unlink(cli, fname_foo_foo);
9194         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9195                 printf("cli_posix_unlink of %s should fail with "
9196                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9197                         "%s instead\n",
9198                         fname_foo_foo,
9199                         nt_errstr(status));
9200                 goto out;
9201         }
9202
9203         status = cli_posix_mkdir(cli, fname_foo, 0777);
9204         if (!NT_STATUS_IS_OK(status)) {
9205                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9206                 goto out;
9207         }
9208
9209         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9210         if (!NT_STATUS_IS_OK(status)) {
9211                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9212                 goto out;
9213         }
9214
9215         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9216         if (!NT_STATUS_IS_OK(status)) {
9217                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9218                 goto out;
9219         }
9220
9221         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9222         if (!NT_STATUS_IS_OK(status)) {
9223                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9224                 goto out;
9225         }
9226
9227         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9228         if (!NT_STATUS_IS_OK(status)) {
9229                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9230                 goto out;
9231         }
9232
9233         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9234         if (!NT_STATUS_IS_OK(status)) {
9235                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9236                 goto out;
9237         }
9238
9239         printf("POSIX mkdir test passed\n");
9240         correct = true;
9241
9242   out:
9243
9244         if (fnum != (uint16_t)-1) {
9245                 cli_close(cli, fnum);
9246                 fnum = (uint16_t)-1;
9247         }
9248
9249         cli_posix_rmdir(cli, fname_foo_foo);
9250         cli_posix_rmdir(cli, fname_foo_Foo);
9251         cli_posix_rmdir(cli, fname_foo);
9252
9253         cli_posix_rmdir(cli, fname_Foo_foo);
9254         cli_posix_rmdir(cli, fname_Foo_Foo);
9255         cli_posix_rmdir(cli, fname_Foo);
9256
9257         if (!torture_close_connection(cli)) {
9258                 correct = false;
9259         }
9260
9261         TALLOC_FREE(frame);
9262         return correct;
9263 }
9264
9265 struct posix_acl_oplock_state {
9266         struct tevent_context *ev;
9267         struct cli_state *cli;
9268         bool *got_break;
9269         bool *acl_ret;
9270         NTSTATUS status;
9271 };
9272
9273 static void posix_acl_oplock_got_break(struct tevent_req *req)
9274 {
9275         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9276                 req, struct posix_acl_oplock_state);
9277         uint16_t fnum;
9278         uint8_t level;
9279         NTSTATUS status;
9280
9281         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9282         TALLOC_FREE(req);
9283         if (!NT_STATUS_IS_OK(status)) {
9284                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9285                        nt_errstr(status));
9286                 return;
9287         }
9288         *state->got_break = true;
9289
9290         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9291                                   NO_OPLOCK);
9292         if (req == NULL) {
9293                 printf("cli_oplock_ack_send failed\n");
9294                 return;
9295         }
9296 }
9297
9298 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9299 {
9300         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9301                 req, struct posix_acl_oplock_state);
9302         size_t ret_size = 0;
9303         char *ret_data = NULL;
9304
9305         state->status = cli_posix_getacl_recv(req,
9306                         state,
9307                         &ret_size,
9308                         &ret_data);
9309
9310         if (!NT_STATUS_IS_OK(state->status)) {
9311                 printf("cli_posix_getacl_recv returned %s\n",
9312                         nt_errstr(state->status));
9313         }
9314         *state->acl_ret = true;
9315 }
9316
9317 static bool run_posix_acl_oplock_test(int dummy)
9318 {
9319         struct tevent_context *ev;
9320         struct cli_state *cli1, *cli2;
9321         struct tevent_req *oplock_req, *getacl_req;
9322         const char *fname = "posix_acl_oplock";
9323         uint16_t fnum;
9324         int saved_use_oplocks = use_oplocks;
9325         NTSTATUS status;
9326         bool correct = true;
9327         bool got_break = false;
9328         bool acl_ret = false;
9329
9330         struct posix_acl_oplock_state *state;
9331
9332         printf("starting posix_acl_oplock test\n");
9333
9334         if (!torture_open_connection(&cli1, 0)) {
9335                 use_level_II_oplocks = false;
9336                 use_oplocks = saved_use_oplocks;
9337                 return false;
9338         }
9339
9340         if (!torture_open_connection(&cli2, 1)) {
9341                 use_level_II_oplocks = false;
9342                 use_oplocks = saved_use_oplocks;
9343                 return false;
9344         }
9345
9346         /* Setup posix on cli2 only. */
9347         status = torture_setup_unix_extensions(cli2);
9348         if (!NT_STATUS_IS_OK(status)) {
9349                 return false;
9350         }
9351
9352         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9353         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9354
9355         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9356
9357         /* Create the file on the Windows connection. */
9358         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9359                           &fnum);
9360         if (!NT_STATUS_IS_OK(status)) {
9361                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9362                 return false;
9363         }
9364
9365         status = cli_close(cli1, fnum);
9366         if (!NT_STATUS_IS_OK(status)) {
9367                 printf("close1 failed (%s)\n", nt_errstr(status));
9368                 return false;
9369         }
9370
9371         cli1->use_oplocks = true;
9372
9373         /* Open with oplock. */
9374         status = cli_ntcreate(cli1,
9375                         fname,
9376                         0,
9377                         FILE_READ_DATA,
9378                         FILE_ATTRIBUTE_NORMAL,
9379                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9380                         FILE_OPEN,
9381                         0,
9382                         0,
9383                         &fnum,
9384                         NULL);
9385
9386         if (!NT_STATUS_IS_OK(status)) {
9387                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9388                 return false;
9389         }
9390
9391         ev = samba_tevent_context_init(talloc_tos());
9392         if (ev == NULL) {
9393                 printf("tevent_context_init failed\n");
9394                 return false;
9395         }
9396
9397         state = talloc_zero(ev, struct posix_acl_oplock_state);
9398         if (state == NULL) {
9399                 printf("talloc failed\n");
9400                 return false;
9401         }
9402         state->ev = ev;
9403         state->cli = cli1;
9404         state->got_break = &got_break;
9405         state->acl_ret = &acl_ret;
9406
9407         oplock_req = cli_smb_oplock_break_waiter_send(
9408                 talloc_tos(), ev, cli1);
9409         if (oplock_req == NULL) {
9410                 printf("cli_smb_oplock_break_waiter_send failed\n");
9411                 return false;
9412         }
9413         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9414
9415         /* Get ACL on POSIX connection - should break oplock. */
9416         getacl_req = cli_posix_getacl_send(talloc_tos(),
9417                                 ev,
9418                                 cli2,
9419                                 fname);
9420         if (getacl_req == NULL) {
9421                 printf("cli_posix_getacl_send failed\n");
9422                 return false;
9423         }
9424         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9425
9426         while (!got_break || !acl_ret) {
9427                 int ret;
9428                 ret = tevent_loop_once(ev);
9429                 if (ret == -1) {
9430                         printf("tevent_loop_once failed: %s\n",
9431                                strerror(errno));
9432                         return false;
9433                 }
9434         }
9435
9436         if (!NT_STATUS_IS_OK(state->status)) {
9437                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9438                 correct = false;
9439         }
9440
9441         status = cli_close(cli1, fnum);
9442         if (!NT_STATUS_IS_OK(status)) {
9443                 printf("close2 failed (%s)\n", nt_errstr(status));
9444                 correct = false;
9445         }
9446
9447         status = cli_unlink(cli1,
9448                         fname,
9449                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9450         if (!NT_STATUS_IS_OK(status)) {
9451                 printf("unlink failed (%s)\n", nt_errstr(status));
9452                 correct = false;
9453         }
9454
9455         if (!torture_close_connection(cli1)) {
9456                 correct = false;
9457         }
9458         if (!torture_close_connection(cli2)) {
9459                 correct = false;
9460         }
9461
9462         if (!got_break) {
9463                 correct = false;
9464         }
9465
9466         printf("finished posix acl oplock test\n");
9467
9468         return correct;
9469 }
9470
9471 static bool run_posix_acl_shareroot_test(int dummy)
9472 {
9473         struct cli_state *cli;
9474         NTSTATUS status;
9475         bool correct = false;
9476         char *posix_acl = NULL;
9477         size_t posix_acl_len = 0;
9478         uint16_t num_file_acls = 0;
9479         uint16_t num_dir_acls = 0;
9480         uint16_t i;
9481         uint32_t expected_size = 0;
9482         bool got_user = false;
9483         bool got_group = false;
9484         bool got_other = false;
9485         TALLOC_CTX *frame = NULL;
9486
9487         frame = talloc_stackframe();
9488
9489         printf("starting posix_acl_shareroot test\n");
9490
9491         if (!torture_open_connection(&cli, 0)) {
9492                 TALLOC_FREE(frame);
9493                 return false;
9494         }
9495
9496         smbXcli_conn_set_sockopt(cli->conn, sockops);
9497
9498         status = torture_setup_unix_extensions(cli);
9499         if (!NT_STATUS_IS_OK(status)) {
9500                 printf("Failed to setup unix extensions\n");
9501                 goto out;
9502         }
9503
9504         /* Get the POSIX ACL on the root of the share. */
9505         status = cli_posix_getacl(cli,
9506                                 ".",
9507                                 frame,
9508                                 &posix_acl_len,
9509                                 &posix_acl);
9510
9511         if (!NT_STATUS_IS_OK(status)) {
9512                 printf("cli_posix_getacl of '.' failed (%s)\n",
9513                         nt_errstr(status));
9514                 goto out;
9515         }
9516
9517         if (posix_acl_len < 6 ||
9518                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9519                 printf("getfacl ., unknown POSIX acl version %u.\n",
9520                         (unsigned int)CVAL(posix_acl,0) );
9521                 goto out;
9522         }
9523
9524         num_file_acls = SVAL(posix_acl,2);
9525         num_dir_acls = SVAL(posix_acl,4);
9526         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9527                                 SMB_POSIX_ACL_ENTRY_SIZE*
9528                                 (num_file_acls+num_dir_acls);
9529
9530         if (posix_acl_len != expected_size) {
9531                 printf("incorrect POSIX acl buffer size "
9532                         "(should be %u, was %u).\n",
9533                         (unsigned int)expected_size,
9534                         (unsigned int)posix_acl_len);
9535                 goto out;
9536         }
9537
9538         /*
9539          * We don't need to know what the ACL's are
9540          * we just need to know we have at least 3
9541          * file entries (u,g,o).
9542          */
9543
9544         for (i = 0; i < num_file_acls; i++) {
9545                 unsigned char tagtype =
9546                         CVAL(posix_acl,
9547                                 SMB_POSIX_ACL_HEADER_SIZE+
9548                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9549
9550                 switch(tagtype) {
9551                         case SMB_POSIX_ACL_USER_OBJ:
9552                                 got_user = true;
9553                                 break;
9554                         case SMB_POSIX_ACL_GROUP_OBJ:
9555                                 got_group = true;
9556                                 break;
9557                         case SMB_POSIX_ACL_OTHER:
9558                                 got_other = true;
9559                                 break;
9560                         default:
9561                                 break;
9562                 }
9563         }
9564
9565         if (!got_user) {
9566                 printf("Missing user entry\n");
9567                 goto out;
9568         }
9569
9570         if (!got_group) {
9571                 printf("Missing group entry\n");
9572                 goto out;
9573         }
9574
9575         if (!got_other) {
9576                 printf("Missing other entry\n");
9577                 goto out;
9578         }
9579
9580         correct = true;
9581
9582   out:
9583
9584         if (!torture_close_connection(cli)) {
9585                 correct = false;
9586         }
9587
9588         printf("finished posix acl shareroot test\n");
9589         TALLOC_FREE(frame);
9590
9591         return correct;
9592 }
9593
9594 static uint32_t open_attrs_table[] = {
9595                 FILE_ATTRIBUTE_NORMAL,
9596                 FILE_ATTRIBUTE_ARCHIVE,
9597                 FILE_ATTRIBUTE_READONLY,
9598                 FILE_ATTRIBUTE_HIDDEN,
9599                 FILE_ATTRIBUTE_SYSTEM,
9600
9601                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9602                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9603                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9604                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9605                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9606                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9607
9608                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9609                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9610                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9611                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9612 };
9613
9614 struct trunc_open_results {
9615         unsigned int num;
9616         uint32_t init_attr;
9617         uint32_t trunc_attr;
9618         uint32_t result_attr;
9619 };
9620
9621 static struct trunc_open_results attr_results[] = {
9622         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9623         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9624         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9625         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9626         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9627         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9628         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9629         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9630         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9631         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9632         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9633         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9634         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9635         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9636         { 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 },
9637         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9638         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9639         { 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 },
9640         { 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 },
9641         { 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 },
9642         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9643         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9644         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9645         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9646         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9647         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9648 };
9649
9650 static bool run_openattrtest(int dummy)
9651 {
9652         static struct cli_state *cli1;
9653         const char *fname = "\\openattr.file";
9654         uint16_t fnum1;
9655         bool correct = True;
9656         uint32_t attr;
9657         unsigned int i, j, k, l;
9658         NTSTATUS status;
9659
9660         printf("starting open attr test\n");
9661
9662         if (!torture_open_connection(&cli1, 0)) {
9663                 return False;
9664         }
9665
9666         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9667
9668         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9669                 cli_setatr(cli1, fname, 0, 0);
9670                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9671
9672                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9673                                        open_attrs_table[i], FILE_SHARE_NONE,
9674                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9675                 if (!NT_STATUS_IS_OK(status)) {
9676                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9677                         return False;
9678                 }
9679
9680                 status = cli_close(cli1, fnum1);
9681                 if (!NT_STATUS_IS_OK(status)) {
9682                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9683                         return False;
9684                 }
9685
9686                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9687                         status = cli_ntcreate(cli1, fname, 0,
9688                                               FILE_READ_DATA|FILE_WRITE_DATA,
9689                                               open_attrs_table[j],
9690                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9691                                               0, 0, &fnum1, NULL);
9692                         if (!NT_STATUS_IS_OK(status)) {
9693                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9694                                         if (attr_results[l].num == k) {
9695                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9696                                                                 k, open_attrs_table[i],
9697                                                                 open_attrs_table[j],
9698                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9699                                                 correct = False;
9700                                         }
9701                                 }
9702
9703                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9704                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9705                                                         k, open_attrs_table[i], open_attrs_table[j],
9706                                                         nt_errstr(status));
9707                                         correct = False;
9708                                 }
9709 #if 0
9710                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9711 #endif
9712                                 k++;
9713                                 continue;
9714                         }
9715
9716                         status = cli_close(cli1, fnum1);
9717                         if (!NT_STATUS_IS_OK(status)) {
9718                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9719                                 return False;
9720                         }
9721
9722                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9723                         if (!NT_STATUS_IS_OK(status)) {
9724                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9725                                 return False;
9726                         }
9727
9728 #if 0
9729                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9730                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9731 #endif
9732
9733                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9734                                 if (attr_results[l].num == k) {
9735                                         if (attr != attr_results[l].result_attr ||
9736                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9737                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9738                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9739                                                 open_attrs_table[i],
9740                                                 open_attrs_table[j],
9741                                                 (unsigned int)attr,
9742                                                 attr_results[l].result_attr);
9743                                                 correct = False;
9744                                         }
9745                                         break;
9746                                 }
9747                         }
9748                         k++;
9749                 }
9750         }
9751
9752         cli_setatr(cli1, fname, 0, 0);
9753         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9754
9755         printf("open attr test %s.\n", correct ? "passed" : "failed");
9756
9757         if (!torture_close_connection(cli1)) {
9758                 correct = False;
9759         }
9760         return correct;
9761 }
9762
9763 static NTSTATUS list_fn(struct file_info *finfo,
9764                     const char *name, void *state)
9765 {
9766         int *matched = (int *)state;
9767         if (matched != NULL) {
9768                 *matched += 1;
9769         }
9770         return NT_STATUS_OK;
9771 }
9772
9773 /*
9774   test directory listing speed
9775  */
9776 static bool run_dirtest(int dummy)
9777 {
9778         int i;
9779         static struct cli_state *cli;
9780         uint16_t fnum;
9781         struct timeval core_start;
9782         bool correct = True;
9783         int matched;
9784
9785         printf("starting directory test\n");
9786
9787         if (!torture_open_connection(&cli, 0)) {
9788                 return False;
9789         }
9790
9791         smbXcli_conn_set_sockopt(cli->conn, sockops);
9792
9793         srandom(0);
9794         for (i=0;i<torture_numops;i++) {
9795                 fstring fname;
9796                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9797                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9798                         fprintf(stderr,"Failed to open %s\n", fname);
9799                         return False;
9800                 }
9801                 cli_close(cli, fnum);
9802         }
9803
9804         core_start = timeval_current();
9805
9806         matched = 0;
9807         cli_list(cli, "a*.*", 0, list_fn, &matched);
9808         printf("Matched %d\n", matched);
9809
9810         matched = 0;
9811         cli_list(cli, "b*.*", 0, list_fn, &matched);
9812         printf("Matched %d\n", matched);
9813
9814         matched = 0;
9815         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9816         printf("Matched %d\n", matched);
9817
9818         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9819
9820         srandom(0);
9821         for (i=0;i<torture_numops;i++) {
9822                 fstring fname;
9823                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9824                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9825         }
9826
9827         if (!torture_close_connection(cli)) {
9828                 correct = False;
9829         }
9830
9831         printf("finished dirtest\n");
9832
9833         return correct;
9834 }
9835
9836 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9837                    void *state)
9838 {
9839         struct cli_state *pcli = (struct cli_state *)state;
9840         fstring fname;
9841         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9842
9843         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9844                 return NT_STATUS_OK;
9845
9846         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9847                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9848                         printf("del_fn: failed to rmdir %s\n,", fname );
9849         } else {
9850                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9851                         printf("del_fn: failed to unlink %s\n,", fname );
9852         }
9853         return NT_STATUS_OK;
9854 }
9855
9856
9857 /*
9858   sees what IOCTLs are supported
9859  */
9860 bool torture_ioctl_test(int dummy)
9861 {
9862         static struct cli_state *cli;
9863         uint16_t device, function;
9864         uint16_t fnum;
9865         const char *fname = "\\ioctl.dat";
9866         DATA_BLOB blob;
9867         NTSTATUS status;
9868
9869         if (!torture_open_connection(&cli, 0)) {
9870                 return False;
9871         }
9872
9873         printf("starting ioctl test\n");
9874
9875         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9876
9877         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9878         if (!NT_STATUS_IS_OK(status)) {
9879                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9880                 return False;
9881         }
9882
9883         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9884         printf("ioctl device info: %s\n", nt_errstr(status));
9885
9886         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9887         printf("ioctl job info: %s\n", nt_errstr(status));
9888
9889         for (device=0;device<0x100;device++) {
9890                 printf("ioctl test with device = 0x%x\n", device);
9891                 for (function=0;function<0x100;function++) {
9892                         uint32_t code = (device<<16) | function;
9893
9894                         status = cli_raw_ioctl(cli, fnum, code, &blob);
9895
9896                         if (NT_STATUS_IS_OK(status)) {
9897                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9898                                        (int)blob.length);
9899                                 data_blob_free(&blob);
9900                         }
9901                 }
9902         }
9903
9904         if (!torture_close_connection(cli)) {
9905                 return False;
9906         }
9907
9908         return True;
9909 }
9910
9911
9912 /*
9913   tries varients of chkpath
9914  */
9915 bool torture_chkpath_test(int dummy)
9916 {
9917         static struct cli_state *cli;
9918         uint16_t fnum;
9919         bool ret;
9920         NTSTATUS status;
9921
9922         if (!torture_open_connection(&cli, 0)) {
9923                 return False;
9924         }
9925
9926         printf("starting chkpath test\n");
9927
9928         /* cleanup from an old run */
9929         torture_deltree(cli, "\\chkpath.dir");
9930
9931         status = cli_mkdir(cli, "\\chkpath.dir");
9932         if (!NT_STATUS_IS_OK(status)) {
9933                 printf("mkdir1 failed : %s\n", nt_errstr(status));
9934                 return False;
9935         }
9936
9937         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9938         if (!NT_STATUS_IS_OK(status)) {
9939                 printf("mkdir2 failed : %s\n", nt_errstr(status));
9940                 return False;
9941         }
9942
9943         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9944                           DENY_NONE, &fnum);
9945         if (!NT_STATUS_IS_OK(status)) {
9946                 printf("open1 failed (%s)\n", nt_errstr(status));
9947                 return False;
9948         }
9949         cli_close(cli, fnum);
9950
9951         status = cli_chkpath(cli, "\\chkpath.dir");
9952         if (!NT_STATUS_IS_OK(status)) {
9953                 printf("chkpath1 failed: %s\n", nt_errstr(status));
9954                 ret = False;
9955         }
9956
9957         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9958         if (!NT_STATUS_IS_OK(status)) {
9959                 printf("chkpath2 failed: %s\n", nt_errstr(status));
9960                 ret = False;
9961         }
9962
9963         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9964         if (!NT_STATUS_IS_OK(status)) {
9965                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9966                                   NT_STATUS_NOT_A_DIRECTORY);
9967         } else {
9968                 printf("* chkpath on a file should fail\n");
9969                 ret = False;
9970         }
9971
9972         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9973         if (!NT_STATUS_IS_OK(status)) {
9974                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9975                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
9976         } else {
9977                 printf("* chkpath on a non existent file should fail\n");
9978                 ret = False;
9979         }
9980
9981         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9982         if (!NT_STATUS_IS_OK(status)) {
9983                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9984                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
9985         } else {
9986                 printf("* chkpath on a non existent component should fail\n");
9987                 ret = False;
9988         }
9989
9990         torture_deltree(cli, "\\chkpath.dir");
9991
9992         if (!torture_close_connection(cli)) {
9993                 return False;
9994         }
9995
9996         return ret;
9997 }
9998
9999 static bool run_eatest(int dummy)
10000 {
10001         static struct cli_state *cli;
10002         const char *fname = "\\eatest.txt";
10003         bool correct = True;
10004         uint16_t fnum;
10005         size_t i, num_eas;
10006         struct ea_struct *ea_list = NULL;
10007         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10008         NTSTATUS status;
10009
10010         printf("starting eatest\n");
10011
10012         if (!torture_open_connection(&cli, 0)) {
10013                 talloc_destroy(mem_ctx);
10014                 return False;
10015         }
10016
10017         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10018
10019         status = cli_ntcreate(cli, fname, 0,
10020                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10021                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10022                               0x4044, 0, &fnum, NULL);
10023         if (!NT_STATUS_IS_OK(status)) {
10024                 printf("open failed - %s\n", nt_errstr(status));
10025                 talloc_destroy(mem_ctx);
10026                 return False;
10027         }
10028
10029         for (i = 0; i < 10; i++) {
10030                 fstring ea_name, ea_val;
10031
10032                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10033                 memset(ea_val, (char)i+1, i+1);
10034                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10035                 if (!NT_STATUS_IS_OK(status)) {
10036                         printf("ea_set of name %s failed - %s\n", ea_name,
10037                                nt_errstr(status));
10038                         talloc_destroy(mem_ctx);
10039                         return False;
10040                 }
10041         }
10042
10043         cli_close(cli, fnum);
10044         for (i = 0; i < 10; i++) {
10045                 fstring ea_name, ea_val;
10046
10047                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10048                 memset(ea_val, (char)i+1, i+1);
10049                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10050                 if (!NT_STATUS_IS_OK(status)) {
10051                         printf("ea_set of name %s failed - %s\n", ea_name,
10052                                nt_errstr(status));
10053                         talloc_destroy(mem_ctx);
10054                         return False;
10055                 }
10056         }
10057
10058         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10059         if (!NT_STATUS_IS_OK(status)) {
10060                 printf("ea_get list failed - %s\n", nt_errstr(status));
10061                 correct = False;
10062         }
10063
10064         printf("num_eas = %d\n", (int)num_eas);
10065
10066         if (num_eas != 20) {
10067                 printf("Should be 20 EA's stored... failing.\n");
10068                 correct = False;
10069         }
10070
10071         for (i = 0; i < num_eas; i++) {
10072                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10073                 dump_data(0, ea_list[i].value.data,
10074                           ea_list[i].value.length);
10075         }
10076
10077         /* Setting EA's to zero length deletes them. Test this */
10078         printf("Now deleting all EA's - case indepenent....\n");
10079
10080 #if 1
10081         cli_set_ea_path(cli, fname, "", "", 0);
10082 #else
10083         for (i = 0; i < 20; i++) {
10084                 fstring ea_name;
10085                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10086                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10087                 if (!NT_STATUS_IS_OK(status)) {
10088                         printf("ea_set of name %s failed - %s\n", ea_name,
10089                                nt_errstr(status));
10090                         talloc_destroy(mem_ctx);
10091                         return False;
10092                 }
10093         }
10094 #endif
10095
10096         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10097         if (!NT_STATUS_IS_OK(status)) {
10098                 printf("ea_get list failed - %s\n", nt_errstr(status));
10099                 correct = False;
10100         }
10101
10102         printf("num_eas = %d\n", (int)num_eas);
10103         for (i = 0; i < num_eas; i++) {
10104                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10105                 dump_data(0, ea_list[i].value.data,
10106                           ea_list[i].value.length);
10107         }
10108
10109         if (num_eas != 0) {
10110                 printf("deleting EA's failed.\n");
10111                 correct = False;
10112         }
10113
10114         /* Try and delete a non existent EA. */
10115         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10116         if (!NT_STATUS_IS_OK(status)) {
10117                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10118                        nt_errstr(status));
10119                 correct = False;
10120         }
10121
10122         talloc_destroy(mem_ctx);
10123         if (!torture_close_connection(cli)) {
10124                 correct = False;
10125         }
10126
10127         return correct;
10128 }
10129
10130 static bool run_dirtest1(int dummy)
10131 {
10132         int i;
10133         static struct cli_state *cli;
10134         uint16_t fnum;
10135         int num_seen;
10136         bool correct = True;
10137
10138         printf("starting directory test\n");
10139
10140         if (!torture_open_connection(&cli, 0)) {
10141                 return False;
10142         }
10143
10144         smbXcli_conn_set_sockopt(cli->conn, sockops);
10145
10146         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10147         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10148         cli_rmdir(cli, "\\LISTDIR");
10149         cli_mkdir(cli, "\\LISTDIR");
10150
10151         /* Create 1000 files and 1000 directories. */
10152         for (i=0;i<1000;i++) {
10153                 fstring fname;
10154                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10155                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10156                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10157                                    0, 0, &fnum, NULL))) {
10158                         fprintf(stderr,"Failed to open %s\n", fname);
10159                         return False;
10160                 }
10161                 cli_close(cli, fnum);
10162         }
10163         for (i=0;i<1000;i++) {
10164                 fstring fname;
10165                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10166                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10167                         fprintf(stderr,"Failed to open %s\n", fname);
10168                         return False;
10169                 }
10170         }
10171
10172         /* Now ensure that doing an old list sees both files and directories. */
10173         num_seen = 0;
10174         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10175         printf("num_seen = %d\n", num_seen );
10176         /* We should see 100 files + 1000 directories + . and .. */
10177         if (num_seen != 2002)
10178                 correct = False;
10179
10180         /* Ensure if we have the "must have" bits we only see the
10181          * relevent entries.
10182          */
10183         num_seen = 0;
10184         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10185         printf("num_seen = %d\n", num_seen );
10186         if (num_seen != 1002)
10187                 correct = False;
10188
10189         num_seen = 0;
10190         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10191         printf("num_seen = %d\n", num_seen );
10192         if (num_seen != 1000)
10193                 correct = False;
10194
10195         /* Delete everything. */
10196         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10197         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10198         cli_rmdir(cli, "\\LISTDIR");
10199
10200 #if 0
10201         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10202         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10203         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10204 #endif
10205
10206         if (!torture_close_connection(cli)) {
10207                 correct = False;
10208         }
10209
10210         printf("finished dirtest1\n");
10211
10212         return correct;
10213 }
10214
10215 static bool run_error_map_extract(int dummy) {
10216
10217         static struct cli_state *c_dos;
10218         static struct cli_state *c_nt;
10219         NTSTATUS status;
10220
10221         uint32_t error;
10222
10223         uint32_t errnum;
10224         uint8_t errclass;
10225
10226         NTSTATUS nt_status;
10227
10228         fstring user;
10229
10230         /* NT-Error connection */
10231
10232         disable_spnego = true;
10233         if (!(c_nt = open_nbt_connection())) {
10234                 disable_spnego = false;
10235                 return False;
10236         }
10237         disable_spnego = false;
10238
10239         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10240                                  PROTOCOL_NT1);
10241
10242         if (!NT_STATUS_IS_OK(status)) {
10243                 printf("%s rejected the NT-error negprot (%s)\n", host,
10244                        nt_errstr(status));
10245                 cli_shutdown(c_nt);
10246                 return False;
10247         }
10248
10249         status = cli_session_setup_anon(c_nt);
10250         if (!NT_STATUS_IS_OK(status)) {
10251                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10252                 return False;
10253         }
10254
10255         /* DOS-Error connection */
10256
10257         disable_spnego = true;
10258         force_dos_errors = true;
10259         if (!(c_dos = open_nbt_connection())) {
10260                 disable_spnego = false;
10261                 force_dos_errors = false;
10262                 return False;
10263         }
10264         disable_spnego = false;
10265         force_dos_errors = false;
10266
10267         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10268                                  PROTOCOL_NT1);
10269         if (!NT_STATUS_IS_OK(status)) {
10270                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10271                        nt_errstr(status));
10272                 cli_shutdown(c_dos);
10273                 return False;
10274         }
10275
10276         status = cli_session_setup_anon(c_dos);
10277         if (!NT_STATUS_IS_OK(status)) {
10278                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10279                         host, nt_errstr(status));
10280                 return False;
10281         }
10282
10283         c_nt->map_dos_errors = false;
10284         c_dos->map_dos_errors = false;
10285
10286         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10287                 struct cli_credentials *user_creds = NULL;
10288
10289                 fstr_sprintf(user, "%X", error);
10290
10291                 user_creds = cli_session_creds_init(talloc_tos(),
10292                                                     user,
10293                                                     workgroup,
10294                                                     NULL, /* realm */
10295                                                     password,
10296                                                     false, /* use_kerberos */
10297                                                     false, /* fallback_after_kerberos */
10298                                                     false, /* use_ccache */
10299                                                     false); /* password_is_nt_hash */
10300                 if (user_creds == NULL) {
10301                         printf("cli_session_creds_init(%s) failed\n", user);
10302                         return false;
10303                 }
10304
10305                 status = cli_session_setup_creds(c_nt, user_creds);
10306                 if (NT_STATUS_IS_OK(status)) {
10307                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10308                 }
10309
10310                 /* Case #1: 32-bit NT errors */
10311                 if (!NT_STATUS_IS_DOS(status)) {
10312                         nt_status = status;
10313                 } else {
10314                         printf("/** Dos error on NT connection! (%s) */\n", 
10315                                nt_errstr(status));
10316                         nt_status = NT_STATUS(0xc0000000);
10317                 }
10318
10319                 status = cli_session_setup_creds(c_dos, user_creds);
10320                 if (NT_STATUS_IS_OK(status)) {
10321                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10322                 }
10323
10324                 /* Case #1: 32-bit NT errors */
10325                 if (NT_STATUS_IS_DOS(status)) {
10326                         printf("/** NT error on DOS connection! (%s) */\n", 
10327                                nt_errstr(status));
10328                         errnum = errclass = 0;
10329                 } else {
10330                         errclass = NT_STATUS_DOS_CLASS(status);
10331                         errnum = NT_STATUS_DOS_CODE(status);
10332                 }
10333
10334                 if (NT_STATUS_V(nt_status) != error) { 
10335                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10336                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10337                                get_nt_error_c_code(talloc_tos(), nt_status));
10338                 }
10339
10340                 printf("\t{%s,\t%s,\t%s},\n", 
10341                        smb_dos_err_class(errclass), 
10342                        smb_dos_err_name(errclass, errnum), 
10343                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10344
10345                 TALLOC_FREE(user_creds);
10346         }
10347         return True;
10348 }
10349
10350 static bool run_sesssetup_bench(int dummy)
10351 {
10352         static struct cli_state *c;
10353         const char *fname = "\\file.dat";
10354         uint16_t fnum;
10355         NTSTATUS status;
10356         int i;
10357
10358         if (!torture_open_connection(&c, 0)) {
10359                 return false;
10360         }
10361
10362         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10363                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10364                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10365         if (!NT_STATUS_IS_OK(status)) {
10366                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10367                 return false;
10368         }
10369
10370         for (i=0; i<torture_numops; i++) {
10371                 status = cli_session_setup_creds(c, torture_creds);
10372                 if (!NT_STATUS_IS_OK(status)) {
10373                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10374                                  __location__, nt_errstr(status));
10375                         return false;
10376                 }
10377
10378                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10379
10380                 status = cli_ulogoff(c);
10381                 if (!NT_STATUS_IS_OK(status)) {
10382                         d_printf("(%s) cli_ulogoff failed: %s\n",
10383                                  __location__, nt_errstr(status));
10384                         return false;
10385                 }
10386         }
10387
10388         return true;
10389 }
10390
10391 static bool subst_test(const char *str, const char *user, const char *domain,
10392                        uid_t uid, gid_t gid, const char *expected)
10393 {
10394         char *subst;
10395         bool result = true;
10396
10397         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10398
10399         if (strcmp(subst, expected) != 0) {
10400                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10401                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10402                        expected);
10403                 result = false;
10404         }
10405
10406         TALLOC_FREE(subst);
10407         return result;
10408 }
10409
10410 static void chain1_open_completion(struct tevent_req *req)
10411 {
10412         uint16_t fnum;
10413         NTSTATUS status;
10414         status = cli_openx_recv(req, &fnum);
10415         TALLOC_FREE(req);
10416
10417         d_printf("cli_openx_recv returned %s: %d\n",
10418                  nt_errstr(status),
10419                  NT_STATUS_IS_OK(status) ? fnum : -1);
10420 }
10421
10422 static void chain1_write_completion(struct tevent_req *req)
10423 {
10424         size_t written;
10425         NTSTATUS status;
10426         status = cli_write_andx_recv(req, &written);
10427         TALLOC_FREE(req);
10428
10429         d_printf("cli_write_andx_recv returned %s: %d\n",
10430                  nt_errstr(status),
10431                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10432 }
10433
10434 static void chain1_close_completion(struct tevent_req *req)
10435 {
10436         NTSTATUS status;
10437         bool *done = (bool *)tevent_req_callback_data_void(req);
10438
10439         status = cli_close_recv(req);
10440         *done = true;
10441
10442         TALLOC_FREE(req);
10443
10444         d_printf("cli_close returned %s\n", nt_errstr(status));
10445 }
10446
10447 static bool run_chain1(int dummy)
10448 {
10449         struct cli_state *cli1;
10450         struct tevent_context *evt = samba_tevent_context_init(NULL);
10451         struct tevent_req *reqs[3], *smbreqs[3];
10452         bool done = false;
10453         const char *str = "foobar";
10454         const char *fname = "\\test_chain";
10455         NTSTATUS status;
10456
10457         printf("starting chain1 test\n");
10458         if (!torture_open_connection(&cli1, 0)) {
10459                 return False;
10460         }
10461
10462         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10463
10464         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10465
10466         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10467                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10468         if (reqs[0] == NULL) return false;
10469         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10470
10471
10472         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10473                                         (const uint8_t *)str, 0, strlen(str)+1,
10474                                         smbreqs, 1, &smbreqs[1]);
10475         if (reqs[1] == NULL) return false;
10476         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10477
10478         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10479         if (reqs[2] == NULL) return false;
10480         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10481
10482         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10483         if (!NT_STATUS_IS_OK(status)) {
10484                 return false;
10485         }
10486
10487         while (!done) {
10488                 tevent_loop_once(evt);
10489         }
10490
10491         torture_close_connection(cli1);
10492         return True;
10493 }
10494
10495 static void chain2_sesssetup_completion(struct tevent_req *req)
10496 {
10497         NTSTATUS status;
10498         status = cli_session_setup_guest_recv(req);
10499         d_printf("sesssetup returned %s\n", nt_errstr(status));
10500 }
10501
10502 static void chain2_tcon_completion(struct tevent_req *req)
10503 {
10504         bool *done = (bool *)tevent_req_callback_data_void(req);
10505         NTSTATUS status;
10506         status = cli_tcon_andx_recv(req);
10507         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10508         *done = true;
10509 }
10510
10511 static bool run_chain2(int dummy)
10512 {
10513         struct cli_state *cli1;
10514         struct tevent_context *evt = samba_tevent_context_init(NULL);
10515         struct tevent_req *reqs[2], *smbreqs[2];
10516         bool done = false;
10517         NTSTATUS status;
10518         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10519
10520         printf("starting chain2 test\n");
10521         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10522                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10523         if (!NT_STATUS_IS_OK(status)) {
10524                 return False;
10525         }
10526
10527         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10528
10529         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10530                                                  &smbreqs[0]);
10531         if (reqs[0] == NULL) return false;
10532         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10533
10534         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10535                                        "?????", NULL, 0, &smbreqs[1]);
10536         if (reqs[1] == NULL) return false;
10537         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10538
10539         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10540         if (!NT_STATUS_IS_OK(status)) {
10541                 return false;
10542         }
10543
10544         while (!done) {
10545                 tevent_loop_once(evt);
10546         }
10547
10548         torture_close_connection(cli1);
10549         return True;
10550 }
10551
10552
10553 struct torture_createdel_state {
10554         struct tevent_context *ev;
10555         struct cli_state *cli;
10556 };
10557
10558 static void torture_createdel_created(struct tevent_req *subreq);
10559 static void torture_createdel_closed(struct tevent_req *subreq);
10560
10561 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10562                                                  struct tevent_context *ev,
10563                                                  struct cli_state *cli,
10564                                                  const char *name)
10565 {
10566         struct tevent_req *req, *subreq;
10567         struct torture_createdel_state *state;
10568
10569         req = tevent_req_create(mem_ctx, &state,
10570                                 struct torture_createdel_state);
10571         if (req == NULL) {
10572                 return NULL;
10573         }
10574         state->ev = ev;
10575         state->cli = cli;
10576
10577         subreq = cli_ntcreate_send(
10578                 state, ev, cli, name, 0,
10579                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10580                 FILE_ATTRIBUTE_NORMAL,
10581                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10582                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10583                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10584
10585         if (tevent_req_nomem(subreq, req)) {
10586                 return tevent_req_post(req, ev);
10587         }
10588         tevent_req_set_callback(subreq, torture_createdel_created, req);
10589         return req;
10590 }
10591
10592 static void torture_createdel_created(struct tevent_req *subreq)
10593 {
10594         struct tevent_req *req = tevent_req_callback_data(
10595                 subreq, struct tevent_req);
10596         struct torture_createdel_state *state = tevent_req_data(
10597                 req, struct torture_createdel_state);
10598         NTSTATUS status;
10599         uint16_t fnum;
10600
10601         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10602         TALLOC_FREE(subreq);
10603         if (tevent_req_nterror(req, status)) {
10604                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10605                            nt_errstr(status)));
10606                 return;
10607         }
10608
10609         subreq = cli_close_send(state, state->ev, state->cli, fnum);
10610         if (tevent_req_nomem(subreq, req)) {
10611                 return;
10612         }
10613         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10614 }
10615
10616 static void torture_createdel_closed(struct tevent_req *subreq)
10617 {
10618         struct tevent_req *req = tevent_req_callback_data(
10619                 subreq, struct tevent_req);
10620         NTSTATUS status;
10621
10622         status = cli_close_recv(subreq);
10623         if (tevent_req_nterror(req, status)) {
10624                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10625                 return;
10626         }
10627         tevent_req_done(req);
10628 }
10629
10630 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10631 {
10632         return tevent_req_simple_recv_ntstatus(req);
10633 }
10634
10635 struct torture_createdels_state {
10636         struct tevent_context *ev;
10637         struct cli_state *cli;
10638         const char *base_name;
10639         int sent;
10640         int received;
10641         int num_files;
10642         struct tevent_req **reqs;
10643 };
10644
10645 static void torture_createdels_done(struct tevent_req *subreq);
10646
10647 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10648                                                   struct tevent_context *ev,
10649                                                   struct cli_state *cli,
10650                                                   const char *base_name,
10651                                                   int num_parallel,
10652                                                   int num_files)
10653 {
10654         struct tevent_req *req;
10655         struct torture_createdels_state *state;
10656         int i;
10657
10658         req = tevent_req_create(mem_ctx, &state,
10659                                 struct torture_createdels_state);
10660         if (req == NULL) {
10661                 return NULL;
10662         }
10663         state->ev = ev;
10664         state->cli = cli;
10665         state->base_name = talloc_strdup(state, base_name);
10666         if (tevent_req_nomem(state->base_name, req)) {
10667                 return tevent_req_post(req, ev);
10668         }
10669         state->num_files = MAX(num_parallel, num_files);
10670         state->sent = 0;
10671         state->received = 0;
10672
10673         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10674         if (tevent_req_nomem(state->reqs, req)) {
10675                 return tevent_req_post(req, ev);
10676         }
10677
10678         for (i=0; i<num_parallel; i++) {
10679                 char *name;
10680
10681                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10682                                        state->sent);
10683                 if (tevent_req_nomem(name, req)) {
10684                         return tevent_req_post(req, ev);
10685                 }
10686                 state->reqs[i] = torture_createdel_send(
10687                         state->reqs, state->ev, state->cli, name);
10688                 if (tevent_req_nomem(state->reqs[i], req)) {
10689                         return tevent_req_post(req, ev);
10690                 }
10691                 name = talloc_move(state->reqs[i], &name);
10692                 tevent_req_set_callback(state->reqs[i],
10693                                         torture_createdels_done, req);
10694                 state->sent += 1;
10695         }
10696         return req;
10697 }
10698
10699 static void torture_createdels_done(struct tevent_req *subreq)
10700 {
10701         struct tevent_req *req = tevent_req_callback_data(
10702                 subreq, struct tevent_req);
10703         struct torture_createdels_state *state = tevent_req_data(
10704                 req, struct torture_createdels_state);
10705         size_t i, num_parallel = talloc_array_length(state->reqs);
10706         NTSTATUS status;
10707         char *name;
10708
10709         status = torture_createdel_recv(subreq);
10710         if (!NT_STATUS_IS_OK(status)){
10711                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10712                            nt_errstr(status)));
10713                 TALLOC_FREE(subreq);
10714                 tevent_req_nterror(req, status);
10715                 return;
10716         }
10717
10718         for (i=0; i<num_parallel; i++) {
10719                 if (subreq == state->reqs[i]) {
10720                         break;
10721                 }
10722         }
10723         if (i == num_parallel) {
10724                 DEBUG(10, ("received something we did not send\n"));
10725                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10726                 return;
10727         }
10728         TALLOC_FREE(state->reqs[i]);
10729
10730         if (state->sent >= state->num_files) {
10731                 tevent_req_done(req);
10732                 return;
10733         }
10734
10735         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10736                                state->sent);
10737         if (tevent_req_nomem(name, req)) {
10738                 return;
10739         }
10740         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10741                                                 state->cli, name);
10742         if (tevent_req_nomem(state->reqs[i], req)) {
10743                 return;
10744         }
10745         name = talloc_move(state->reqs[i], &name);
10746         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10747         state->sent += 1;
10748 }
10749
10750 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10751 {
10752         return tevent_req_simple_recv_ntstatus(req);
10753 }
10754
10755 struct swallow_notify_state {
10756         struct tevent_context *ev;
10757         struct cli_state *cli;
10758         uint16_t fnum;
10759         uint32_t completion_filter;
10760         bool recursive;
10761         bool (*fn)(uint32_t action, const char *name, void *priv);
10762         void *priv;
10763 };
10764
10765 static void swallow_notify_done(struct tevent_req *subreq);
10766
10767 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10768                                               struct tevent_context *ev,
10769                                               struct cli_state *cli,
10770                                               uint16_t fnum,
10771                                               uint32_t completion_filter,
10772                                               bool recursive,
10773                                               bool (*fn)(uint32_t action,
10774                                                          const char *name,
10775                                                          void *priv),
10776                                               void *priv)
10777 {
10778         struct tevent_req *req, *subreq;
10779         struct swallow_notify_state *state;
10780
10781         req = tevent_req_create(mem_ctx, &state,
10782                                 struct swallow_notify_state);
10783         if (req == NULL) {
10784                 return NULL;
10785         }
10786         state->ev = ev;
10787         state->cli = cli;
10788         state->fnum = fnum;
10789         state->completion_filter = completion_filter;
10790         state->recursive = recursive;
10791         state->fn = fn;
10792         state->priv = priv;
10793
10794         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10795                                  0xffff, state->completion_filter,
10796                                  state->recursive);
10797         if (tevent_req_nomem(subreq, req)) {
10798                 return tevent_req_post(req, ev);
10799         }
10800         tevent_req_set_callback(subreq, swallow_notify_done, req);
10801         return req;
10802 }
10803
10804 static void swallow_notify_done(struct tevent_req *subreq)
10805 {
10806         struct tevent_req *req = tevent_req_callback_data(
10807                 subreq, struct tevent_req);
10808         struct swallow_notify_state *state = tevent_req_data(
10809                 req, struct swallow_notify_state);
10810         NTSTATUS status;
10811         uint32_t i, num_changes;
10812         struct notify_change *changes;
10813
10814         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10815         TALLOC_FREE(subreq);
10816         if (!NT_STATUS_IS_OK(status)) {
10817                 DEBUG(10, ("cli_notify_recv returned %s\n",
10818                            nt_errstr(status)));
10819                 tevent_req_nterror(req, status);
10820                 return;
10821         }
10822
10823         for (i=0; i<num_changes; i++) {
10824                 state->fn(changes[i].action, changes[i].name, state->priv);
10825         }
10826         TALLOC_FREE(changes);
10827
10828         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10829                                  0xffff, state->completion_filter,
10830                                  state->recursive);
10831         if (tevent_req_nomem(subreq, req)) {
10832                 return;
10833         }
10834         tevent_req_set_callback(subreq, swallow_notify_done, req);
10835 }
10836
10837 static bool print_notifies(uint32_t action, const char *name, void *priv)
10838 {
10839         if (DEBUGLEVEL > 5) {
10840                 d_printf("%d %s\n", (int)action, name);
10841         }
10842         return true;
10843 }
10844
10845 static void notify_bench_done(struct tevent_req *req)
10846 {
10847         int *num_finished = (int *)tevent_req_callback_data_void(req);
10848         *num_finished += 1;
10849 }
10850
10851 static bool run_notify_bench(int dummy)
10852 {
10853         const char *dname = "\\notify-bench";
10854         struct tevent_context *ev;
10855         NTSTATUS status;
10856         uint16_t dnum;
10857         struct tevent_req *req1;
10858         struct tevent_req *req2 = NULL;
10859         int i, num_unc_names;
10860         int num_finished = 0;
10861
10862         printf("starting notify-bench test\n");
10863
10864         if (use_multishare_conn) {
10865                 char **unc_list;
10866                 unc_list = file_lines_load(multishare_conn_fname,
10867                                            &num_unc_names, 0, NULL);
10868                 if (!unc_list || num_unc_names <= 0) {
10869                         d_printf("Failed to load unc names list from '%s'\n",
10870                                  multishare_conn_fname);
10871                         return false;
10872                 }
10873                 TALLOC_FREE(unc_list);
10874         } else {
10875                 num_unc_names = 1;
10876         }
10877
10878         ev = samba_tevent_context_init(talloc_tos());
10879         if (ev == NULL) {
10880                 d_printf("tevent_context_init failed\n");
10881                 return false;
10882         }
10883
10884         for (i=0; i<num_unc_names; i++) {
10885                 struct cli_state *cli;
10886                 char *base_fname;
10887
10888                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10889                                              dname, i);
10890                 if (base_fname == NULL) {
10891                         return false;
10892                 }
10893
10894                 if (!torture_open_connection(&cli, i)) {
10895                         return false;
10896                 }
10897
10898                 status = cli_ntcreate(cli, dname, 0,
10899                                       MAXIMUM_ALLOWED_ACCESS,
10900                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10901                                       FILE_SHARE_DELETE,
10902                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10903                                       &dnum, NULL);
10904
10905                 if (!NT_STATUS_IS_OK(status)) {
10906                         d_printf("Could not create %s: %s\n", dname,
10907                                  nt_errstr(status));
10908                         return false;
10909                 }
10910
10911                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10912                                            FILE_NOTIFY_CHANGE_FILE_NAME |
10913                                            FILE_NOTIFY_CHANGE_DIR_NAME |
10914                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
10915                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
10916                                            false, print_notifies, NULL);
10917                 if (req1 == NULL) {
10918                         d_printf("Could not create notify request\n");
10919                         return false;
10920                 }
10921
10922                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10923                                                base_fname, 10, torture_numops);
10924                 if (req2 == NULL) {
10925                         d_printf("Could not create createdels request\n");
10926                         return false;
10927                 }
10928                 TALLOC_FREE(base_fname);
10929
10930                 tevent_req_set_callback(req2, notify_bench_done,
10931                                         &num_finished);
10932         }
10933
10934         while (num_finished < num_unc_names) {
10935                 int ret;
10936                 ret = tevent_loop_once(ev);
10937                 if (ret != 0) {
10938                         d_printf("tevent_loop_once failed\n");
10939                         return false;
10940                 }
10941         }
10942
10943         if (!tevent_req_poll(req2, ev)) {
10944                 d_printf("tevent_req_poll failed\n");
10945         }
10946
10947         status = torture_createdels_recv(req2);
10948         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10949
10950         return true;
10951 }
10952
10953 static bool run_mangle1(int dummy)
10954 {
10955         struct cli_state *cli;
10956         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10957         uint16_t fnum;
10958         fstring alt_name;
10959         NTSTATUS status;
10960         time_t change_time, access_time, write_time;
10961         off_t size;
10962         uint32_t attr;
10963
10964         printf("starting mangle1 test\n");
10965         if (!torture_open_connection(&cli, 0)) {
10966                 return False;
10967         }
10968
10969         smbXcli_conn_set_sockopt(cli->conn, sockops);
10970
10971         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10972                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10973                               0, 0, &fnum, NULL);
10974         if (!NT_STATUS_IS_OK(status)) {
10975                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10976                 return false;
10977         }
10978         cli_close(cli, fnum);
10979
10980         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10981         if (!NT_STATUS_IS_OK(status)) {
10982                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10983                          nt_errstr(status));
10984                 return false;
10985         }
10986         d_printf("alt_name: %s\n", alt_name);
10987
10988         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10989         if (!NT_STATUS_IS_OK(status)) {
10990                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10991                          nt_errstr(status));
10992                 return false;
10993         }
10994         cli_close(cli, fnum);
10995
10996         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10997                                 &write_time, &size, &attr);
10998         if (!NT_STATUS_IS_OK(status)) {
10999                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11000                          nt_errstr(status));
11001                 return false;
11002         }
11003
11004         return true;
11005 }
11006
11007 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11008                                                  const char *mask,
11009                                                  void *state)
11010 {
11011         if (f->short_name == NULL) {
11012                 return NT_STATUS_OK;
11013         }
11014
11015         if (strlen(f->short_name) == 0) {
11016                 return NT_STATUS_OK;
11017         }
11018
11019         printf("unexpected shortname: %s\n", f->short_name);
11020
11021         return NT_STATUS_OBJECT_NAME_INVALID;
11022 }
11023
11024 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11025                                             const char *mask,
11026                                             void *state)
11027 {
11028         char *name = state;
11029
11030         printf("name: %s\n", f->name);
11031         fstrcpy(name, f->name);
11032         return NT_STATUS_OK;
11033 }
11034
11035 static bool run_mangle_illegal(int dummy)
11036 {
11037         struct cli_state *cli = NULL;
11038         struct cli_state *cli_posix = NULL;
11039         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11040         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11041         char *mangled_path = NULL;
11042         uint16_t fnum;
11043         fstring name;
11044         fstring alt_name;
11045         NTSTATUS status;
11046
11047         printf("starting mangle-illegal test\n");
11048
11049         if (!torture_open_connection(&cli, 0)) {
11050                 return False;
11051         }
11052
11053         smbXcli_conn_set_sockopt(cli->conn, sockops);
11054
11055         if (!torture_open_connection(&cli_posix, 0)) {
11056                 return false;
11057         }
11058
11059         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11060
11061         status = torture_setup_unix_extensions(cli_posix);
11062         if (!NT_STATUS_IS_OK(status)) {
11063                 return false;
11064         }
11065
11066         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11067         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11068         if (!NT_STATUS_IS_OK(status)) {
11069                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11070                 return False;
11071         }
11072
11073         /*
11074          * Create a file with illegal NTFS characters and test that we
11075          * get a usable mangled name
11076          */
11077
11078         cli_setatr(cli_posix, illegal_fname, 0, 0);
11079         cli_posix_unlink(cli_posix, illegal_fname);
11080
11081         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11082                                 0600, &fnum);
11083         if (!NT_STATUS_IS_OK(status)) {
11084                 printf("POSIX create of %s failed (%s)\n",
11085                        illegal_fname, nt_errstr(status));
11086                 return false;
11087         }
11088
11089         status = cli_close(cli_posix, fnum);
11090         if (!NT_STATUS_IS_OK(status)) {
11091                 printf("close failed (%s)\n", nt_errstr(status));
11092                 return false;
11093         }
11094
11095         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11096         if (!NT_STATUS_IS_OK(status)) {
11097                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11098                 return false;
11099         }
11100
11101         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11102         if (mangled_path == NULL) {
11103                 return false;
11104         }
11105
11106         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11107         if (!NT_STATUS_IS_OK(status)) {
11108                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11109                 TALLOC_FREE(mangled_path);
11110                 return false;
11111         }
11112         TALLOC_FREE(mangled_path);
11113         cli_close(cli, fnum);
11114
11115         cli_setatr(cli_posix, illegal_fname, 0, 0);
11116         cli_posix_unlink(cli_posix, illegal_fname);
11117
11118         /*
11119          * Create a file with a long name and check that we got *no* short name.
11120          */
11121
11122         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11123                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11124                               0, 0, &fnum, NULL);
11125         if (!NT_STATUS_IS_OK(status)) {
11126                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11127                 return false;
11128         }
11129         cli_close(cli, fnum);
11130
11131         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11132         if (!NT_STATUS_IS_OK(status)) {
11133                 d_printf("cli_list failed\n");
11134                 return false;
11135         }
11136
11137         cli_unlink(cli, fname, 0);
11138         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11139
11140         if (!torture_close_connection(cli_posix)) {
11141                 return false;
11142         }
11143
11144         if (!torture_close_connection(cli)) {
11145                 return false;
11146         }
11147
11148         return true;
11149 }
11150
11151 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11152 {
11153         size_t *to_pull = (size_t *)priv;
11154         size_t thistime = *to_pull;
11155
11156         thistime = MIN(thistime, n);
11157         if (thistime == 0) {
11158                 return 0;
11159         }
11160
11161         memset(buf, 0, thistime);
11162         *to_pull -= thistime;
11163         return thistime;
11164 }
11165
11166 static bool run_windows_write(int dummy)
11167 {
11168         struct cli_state *cli1;
11169         uint16_t fnum;
11170         int i;
11171         bool ret = false;
11172         const char *fname = "\\writetest.txt";
11173         struct timeval start_time;
11174         double seconds;
11175         double kbytes;
11176         NTSTATUS status;
11177
11178         printf("starting windows_write test\n");
11179         if (!torture_open_connection(&cli1, 0)) {
11180                 return False;
11181         }
11182
11183         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11184         if (!NT_STATUS_IS_OK(status)) {
11185                 printf("open failed (%s)\n", nt_errstr(status));
11186                 return False;
11187         }
11188
11189         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11190
11191         start_time = timeval_current();
11192
11193         for (i=0; i<torture_numops; i++) {
11194                 uint8_t c = 0;
11195                 off_t start = i * torture_blocksize;
11196                 size_t to_pull = torture_blocksize - 1;
11197
11198                 status = cli_writeall(cli1, fnum, 0, &c,
11199                                       start + torture_blocksize - 1, 1, NULL);
11200                 if (!NT_STATUS_IS_OK(status)) {
11201                         printf("cli_write failed: %s\n", nt_errstr(status));
11202                         goto fail;
11203                 }
11204
11205                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11206                                   null_source, &to_pull);
11207                 if (!NT_STATUS_IS_OK(status)) {
11208                         printf("cli_push returned: %s\n", nt_errstr(status));
11209                         goto fail;
11210                 }
11211         }
11212
11213         seconds = timeval_elapsed(&start_time);
11214         kbytes = (double)torture_blocksize * torture_numops;
11215         kbytes /= 1024;
11216
11217         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11218                (double)seconds, (int)(kbytes/seconds));
11219
11220         ret = true;
11221  fail:
11222         cli_close(cli1, fnum);
11223         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11224         torture_close_connection(cli1);
11225         return ret;
11226 }
11227
11228 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11229 {
11230         size_t max_pdu = 0x1FFFF;
11231
11232         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11233                 max_pdu = 0xFFFFFF;
11234         }
11235
11236         if (smb1cli_conn_signing_is_active(cli->conn)) {
11237                 max_pdu = 0x1FFFF;
11238         }
11239
11240         if (smb1cli_conn_encryption_on(cli->conn)) {
11241                 max_pdu = CLI_BUFFER_SIZE;
11242         }
11243
11244         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11245                 len_requested &= 0xFFFF;
11246         }
11247
11248         return MIN(len_requested,
11249                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11250 }
11251
11252 static bool check_read_call(struct cli_state *cli,
11253                             uint16_t fnum,
11254                             uint8_t *buf,
11255                             size_t len_requested)
11256 {
11257         NTSTATUS status;
11258         struct tevent_req *subreq = NULL;
11259         ssize_t len_read = 0;
11260         size_t len_expected = 0;
11261         struct tevent_context *ev = NULL;
11262
11263         ev = samba_tevent_context_init(talloc_tos());
11264         if (ev == NULL) {
11265                 return false;
11266         }
11267
11268         subreq = cli_read_andx_send(talloc_tos(),
11269                                     ev,
11270                                     cli,
11271                                     fnum,
11272                                     0,
11273                                     len_requested);
11274
11275         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11276                 return false;
11277         }
11278
11279         status = cli_read_andx_recv(subreq, &len_read, &buf);
11280         if (!NT_STATUS_IS_OK(status)) {
11281                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11282                 return false;
11283         }
11284
11285         TALLOC_FREE(subreq);
11286         TALLOC_FREE(ev);
11287
11288         len_expected = calc_expected_return(cli, len_requested);
11289
11290         if (len_expected > 0x10000 && len_read == 0x10000) {
11291                 /* Windows servers only return a max of 0x10000,
11292                    doesn't matter if you set CAP_LARGE_READX in
11293                    the client sessionsetupX call or not. */
11294                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11295                         (unsigned int)len_requested);
11296         } else if (len_read != len_expected) {
11297                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11298                         (unsigned int)len_requested,
11299                         (unsigned int)len_read,
11300                         (unsigned int)len_expected);
11301                 return false;
11302         } else {
11303                 d_printf("Correct read reply.\n");
11304         }
11305
11306         return true;
11307 }
11308
11309 /* Test large readX variants. */
11310 static bool large_readx_tests(struct cli_state *cli,
11311                                 uint16_t fnum,
11312                                 uint8_t *buf)
11313 {
11314         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11315         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11316                 return false;
11317         }
11318         /* A read of 0x10000 should return 0x10000 bytes. */
11319         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11320                 return false;
11321         }
11322         /* A read of 0x10000 should return 0x10001 bytes. */
11323         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11324                 return false;
11325         }
11326         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11327            the requested number of bytes. */
11328         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11329                 return false;
11330         }
11331         /* A read of 1MB should return 1MB bytes (on Samba). */
11332         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11333                 return false;
11334         }
11335
11336         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11337                 return false;
11338         }
11339         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11340                 return false;
11341         }
11342         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11343                 return false;
11344         }
11345         return true;
11346 }
11347
11348 static bool run_large_readx(int dummy)
11349 {
11350         uint8_t *buf = NULL;
11351         struct cli_state *cli1 = NULL;
11352         struct cli_state *cli2 = NULL;
11353         bool correct = false;
11354         const char *fname = "\\large_readx.dat";
11355         NTSTATUS status;
11356         uint16_t fnum1 = UINT16_MAX;
11357         uint32_t normal_caps = 0;
11358         size_t file_size = 20*1024*1024;
11359         TALLOC_CTX *frame = talloc_stackframe();
11360         size_t i;
11361         struct {
11362                 const char *name;
11363                 enum smb_signing_setting signing_setting;
11364                 enum protocol_types protocol;
11365         } runs[] = {
11366                 {
11367                         .name = "NT1",
11368                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11369                         .protocol = PROTOCOL_NT1,
11370                 },{
11371                         .name = "NT1 - SIGNING_REQUIRED",
11372                         .signing_setting = SMB_SIGNING_REQUIRED,
11373                         .protocol = PROTOCOL_NT1,
11374                 },
11375         };
11376
11377         printf("starting large_readx test\n");
11378
11379         if (!torture_open_connection(&cli1, 0)) {
11380                 goto out;
11381         }
11382
11383         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11384
11385         if (!(normal_caps & CAP_LARGE_READX)) {
11386                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11387                         (unsigned int)normal_caps);
11388                 goto out;
11389         }
11390
11391         /* Create a file of size 4MB. */
11392         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11393                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11394                         0, 0, &fnum1, NULL);
11395
11396         if (!NT_STATUS_IS_OK(status)) {
11397                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11398                 goto out;
11399         }
11400
11401         /* Write file_size bytes. */
11402         buf = talloc_zero_array(frame, uint8_t, file_size);
11403         if (buf == NULL) {
11404                 goto out;
11405         }
11406
11407         status = cli_writeall(cli1,
11408                               fnum1,
11409                               0,
11410                               buf,
11411                               0,
11412                               file_size,
11413                               NULL);
11414         if (!NT_STATUS_IS_OK(status)) {
11415                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11416                 goto out;
11417         }
11418
11419         status = cli_close(cli1, fnum1);
11420         if (!NT_STATUS_IS_OK(status)) {
11421                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11422                 goto out;
11423         }
11424
11425         fnum1 = UINT16_MAX;
11426
11427         for (i=0; i < ARRAY_SIZE(runs); i++) {
11428                 enum smb_signing_setting saved_signing_setting = signing_state;
11429                 uint16_t fnum2 = -1;
11430
11431                 if (do_encrypt &&
11432                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11433                 {
11434                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11435                         continue;
11436                 }
11437
11438                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11439
11440                 signing_state = runs[i].signing_setting;
11441                 cli2 = open_nbt_connection();
11442                 signing_state = saved_signing_setting;
11443                 if (cli2 == NULL) {
11444                         goto out;
11445                 }
11446
11447                 status = smbXcli_negprot(cli2->conn,
11448                                          cli2->timeout,
11449                                          runs[i].protocol,
11450                                          runs[i].protocol);
11451                 if (!NT_STATUS_IS_OK(status)) {
11452                         goto out;
11453                 }
11454
11455                 status = cli_session_setup_creds(cli2, torture_creds);
11456                 if (!NT_STATUS_IS_OK(status)) {
11457                         goto out;
11458                 }
11459
11460                 status = cli_tree_connect(cli2,
11461                                         share,
11462                                         "?????",
11463                                         password);
11464                 if (!NT_STATUS_IS_OK(status)) {
11465                         goto out;
11466                 }
11467
11468                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11469
11470                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11471
11472                 if (!(normal_caps & CAP_LARGE_READX)) {
11473                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11474                                 (unsigned int)normal_caps);
11475                         goto out;
11476                 }
11477
11478                 if (do_encrypt) {
11479                         if (force_cli_encryption(cli2, share) == false) {
11480                                 goto out;
11481                         }
11482                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11483                         uint16_t major, minor;
11484                         uint32_t caplow, caphigh;
11485
11486                         status = cli_unix_extensions_version(cli2,
11487                                                              &major, &minor,
11488                                                              &caplow, &caphigh);
11489                         if (!NT_STATUS_IS_OK(status)) {
11490                                 goto out;
11491                         }
11492                 }
11493
11494                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11495                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11496                                 0, 0, &fnum2, NULL);
11497                 if (!NT_STATUS_IS_OK(status)) {
11498                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11499                         goto out;
11500                 }
11501
11502                 /* All reads must return less than file_size bytes. */
11503                 if (!large_readx_tests(cli2, fnum2, buf)) {
11504                         goto out;
11505                 }
11506
11507                 status = cli_close(cli2, fnum2);
11508                 if (!NT_STATUS_IS_OK(status)) {
11509                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11510                         goto out;
11511                 }
11512                 fnum2 = -1;
11513
11514                 if (!torture_close_connection(cli2)) {
11515                         goto out;
11516                 }
11517                 cli2 = NULL;
11518         }
11519
11520         correct = true;
11521         printf("Success on large_readx test\n");
11522
11523   out:
11524
11525         if (cli2) {
11526                 if (!torture_close_connection(cli2)) {
11527                         correct = false;
11528                 }
11529         }
11530
11531         if (cli1) {
11532                 if (fnum1 != UINT16_MAX) {
11533                         status = cli_close(cli1, fnum1);
11534                         if (!NT_STATUS_IS_OK(status)) {
11535                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11536                         }
11537                         fnum1 = UINT16_MAX;
11538                 }
11539
11540                 status = cli_unlink(cli1, fname,
11541                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11542                 if (!NT_STATUS_IS_OK(status)) {
11543                         printf("unlink failed (%s)\n", nt_errstr(status));
11544                 }
11545
11546                 if (!torture_close_connection(cli1)) {
11547                         correct = false;
11548                 }
11549         }
11550
11551         TALLOC_FREE(frame);
11552
11553         printf("finished large_readx test\n");
11554         return correct;
11555 }
11556
11557 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11558                                   const char *mask,
11559                                   void *private_data)
11560 {
11561         uint32_t *p_attr = (uint32_t *)private_data;
11562
11563         if (strequal(finfo->name, test_filename)) {
11564                 *p_attr = finfo->attr;
11565         }
11566
11567         return NT_STATUS_OK;
11568 }
11569
11570 static bool run_msdfs_attribute(int dummy)
11571 {
11572         static struct cli_state *cli;
11573         bool correct = false;
11574         uint32_t attr = 0;
11575         NTSTATUS status;
11576
11577         printf("Starting MSDFS-ATTRIBUTE test\n");
11578
11579         if (test_filename == NULL || test_filename[0] == '\0') {
11580                 printf("MSDFS-ATTRIBUTE test "
11581                         "needs -f filename-of-msdfs-link\n");
11582                 return false;
11583         }
11584
11585         /*
11586          * NB. We use torture_open_connection_flags() not
11587          * torture_open_connection() as the latter forces
11588          * SMB1.
11589          */
11590         if (!torture_open_connection_flags(&cli, 0, 0)) {
11591                 return false;
11592         }
11593
11594         smbXcli_conn_set_sockopt(cli->conn, sockops);
11595
11596         status = cli_list(cli,
11597                         "*",
11598                         FILE_ATTRIBUTE_DIRECTORY,
11599                         msdfs_attribute_list_fn,
11600                         &attr);
11601
11602         if (!NT_STATUS_IS_OK(status)) {
11603                 printf("cli_list failed with %s\n",
11604                         nt_errstr(status));
11605                 goto out;
11606         }
11607         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11608                 printf("file %s should have "
11609                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11610                         test_filename,
11611                         (unsigned int)attr);
11612                 goto out;
11613         }
11614
11615         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11616                 printf("file %s should have "
11617                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11618                         test_filename,
11619                         (unsigned int)attr);
11620                 goto out;
11621         }
11622
11623         correct = true;
11624
11625   out:
11626
11627         torture_close_connection(cli);
11628         return correct;
11629 }
11630
11631 static bool run_cli_echo(int dummy)
11632 {
11633         struct cli_state *cli;
11634         NTSTATUS status;
11635
11636         printf("starting cli_echo test\n");
11637         if (!torture_open_connection(&cli, 0)) {
11638                 return false;
11639         }
11640         smbXcli_conn_set_sockopt(cli->conn, sockops);
11641
11642         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11643
11644         d_printf("cli_echo returned %s\n", nt_errstr(status));
11645
11646         torture_close_connection(cli);
11647         return NT_STATUS_IS_OK(status);
11648 }
11649
11650 static int splice_status(off_t written, void *priv)
11651 {
11652         return true;
11653 }
11654
11655 static bool run_cli_splice(int dummy)
11656 {
11657         uint8_t *buf = NULL;
11658         struct cli_state *cli1 = NULL;
11659         bool correct = false;
11660         const char *fname_src = "\\splice_src.dat";
11661         const char *fname_dst = "\\splice_dst.dat";
11662         NTSTATUS status;
11663         uint16_t fnum1 = UINT16_MAX;
11664         uint16_t fnum2 = UINT16_MAX;
11665         size_t file_size = 2*1024*1024;
11666         size_t splice_size = 1*1024*1024 + 713;
11667         uint8_t digest1[16], digest2[16];
11668         off_t written = 0;
11669         size_t nread = 0;
11670         TALLOC_CTX *frame = talloc_stackframe();
11671
11672         printf("starting cli_splice test\n");
11673
11674         if (!torture_open_connection(&cli1, 0)) {
11675                 goto out;
11676         }
11677
11678         cli_unlink(cli1, fname_src,
11679                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680         cli_unlink(cli1, fname_dst,
11681                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11682
11683         /* Create a file */
11684         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11685                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11686                         0, 0, &fnum1, NULL);
11687
11688         if (!NT_STATUS_IS_OK(status)) {
11689                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11690                 goto out;
11691         }
11692
11693         /* Write file_size bytes - must be bigger than splice_size. */
11694         buf = talloc_zero_array(frame, uint8_t, file_size);
11695         if (buf == NULL) {
11696                 d_printf("talloc_fail\n");
11697                 goto out;
11698         }
11699
11700         /* Fill it with random numbers. */
11701         generate_random_buffer(buf, file_size);
11702
11703         /* MD5 the first 1MB + 713 bytes. */
11704         gnutls_hash_fast(GNUTLS_DIG_MD5,
11705                          buf,
11706                          splice_size,
11707                          digest1);
11708
11709         status = cli_writeall(cli1,
11710                               fnum1,
11711                               0,
11712                               buf,
11713                               0,
11714                               file_size,
11715                               NULL);
11716         if (!NT_STATUS_IS_OK(status)) {
11717                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11718                 goto out;
11719         }
11720
11721         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11722                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11723                         0, 0, &fnum2, NULL);
11724
11725         if (!NT_STATUS_IS_OK(status)) {
11726                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11727                 goto out;
11728         }
11729
11730         /* Now splice 1MB + 713 bytes. */
11731         status = cli_splice(cli1,
11732                                 cli1,
11733                                 fnum1,
11734                                 fnum2,
11735                                 splice_size,
11736                                 0,
11737                                 0,
11738                                 &written,
11739                                 splice_status,
11740                                 NULL);
11741
11742         if (!NT_STATUS_IS_OK(status)) {
11743                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11744                 goto out;
11745         }
11746
11747         /* Clear the old buffer. */
11748         memset(buf, '\0', file_size);
11749
11750         /* Read the new file. */
11751         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11752         if (!NT_STATUS_IS_OK(status)) {
11753                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11754                 goto out;
11755         }
11756         if (nread != splice_size) {
11757                 d_printf("bad read of 0x%x, should be 0x%x\n",
11758                         (unsigned int)nread,
11759                         (unsigned int)splice_size);
11760                 goto out;
11761         }
11762
11763         /* MD5 the first 1MB + 713 bytes. */
11764         gnutls_hash_fast(GNUTLS_DIG_MD5,
11765                          buf,
11766                          splice_size,
11767                          digest2);
11768
11769         /* Must be the same. */
11770         if (memcmp(digest1, digest2, 16) != 0) {
11771                 d_printf("bad MD5 compare\n");
11772                 goto out;
11773         }
11774
11775         correct = true;
11776         printf("Success on cli_splice test\n");
11777
11778   out:
11779
11780         if (cli1) {
11781                 if (fnum1 != UINT16_MAX) {
11782                         cli_close(cli1, fnum1);
11783                 }
11784                 if (fnum2 != UINT16_MAX) {
11785                         cli_close(cli1, fnum2);
11786                 }
11787
11788                 cli_unlink(cli1, fname_src,
11789                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11790                 cli_unlink(cli1, fname_dst,
11791                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11792
11793                 if (!torture_close_connection(cli1)) {
11794                         correct = false;
11795                 }
11796         }
11797
11798         TALLOC_FREE(frame);
11799         return correct;
11800 }
11801
11802 static bool run_uid_regression_test(int dummy)
11803 {
11804         static struct cli_state *cli;
11805         int16_t old_vuid;
11806         int32_t old_cnum;
11807         bool correct = True;
11808         struct smbXcli_tcon *tcon_copy = NULL;
11809         NTSTATUS status;
11810
11811         printf("starting uid regression test\n");
11812
11813         if (!torture_open_connection(&cli, 0)) {
11814                 return False;
11815         }
11816
11817         smbXcli_conn_set_sockopt(cli->conn, sockops);
11818
11819         /* Ok - now save then logoff our current user. */
11820         old_vuid = cli_state_get_uid(cli);
11821
11822         status = cli_ulogoff(cli);
11823         if (!NT_STATUS_IS_OK(status)) {
11824                 d_printf("(%s) cli_ulogoff failed: %s\n",
11825                          __location__, nt_errstr(status));
11826                 correct = false;
11827                 goto out;
11828         }
11829
11830         cli_state_set_uid(cli, old_vuid);
11831
11832         /* Try an operation. */
11833         status = cli_mkdir(cli, "\\uid_reg_test");
11834         if (NT_STATUS_IS_OK(status)) {
11835                 d_printf("(%s) cli_mkdir succeeded\n",
11836                          __location__);
11837                 correct = false;
11838                 goto out;
11839         } else {
11840                 /* Should be bad uid. */
11841                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11842                                  NT_STATUS_USER_SESSION_DELETED)) {
11843                         correct = false;
11844                         goto out;
11845                 }
11846         }
11847
11848         old_cnum = cli_state_get_tid(cli);
11849         /*
11850          * This is an SMB1-only test.
11851          * Copy the tcon, not "save/restore".
11852          *
11853          * In SMB1 the cli_tdis() below frees
11854          * cli->smb1.tcon so we need a copy
11855          * of the struct to put back for the
11856          * second tdis call with invalid vuid.
11857          *
11858          * This is a test-only hack. Real client code
11859          * uses cli_state_save_tcon()/cli_state_restore_tcon().
11860          */
11861         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11862         if (tcon_copy == NULL) {
11863                 correct = false;
11864                 goto out;
11865         }
11866
11867         /* Now try a SMBtdis with the invalid vuid set to zero. */
11868         cli_state_set_uid(cli, 0);
11869
11870         /* This should succeed. */
11871         status = cli_tdis(cli);
11872
11873         if (NT_STATUS_IS_OK(status)) {
11874                 d_printf("First tdis with invalid vuid should succeed.\n");
11875         } else {
11876                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11877                 correct = false;
11878                 cli->smb1.tcon = tcon_copy;
11879                 goto out;
11880         }
11881
11882         cli->smb1.tcon = tcon_copy;
11883         cli_state_set_uid(cli, old_vuid);
11884         cli_state_set_tid(cli, old_cnum);
11885
11886         /* This should fail. */
11887         status = cli_tdis(cli);
11888         if (NT_STATUS_IS_OK(status)) {
11889                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11890                 correct = false;
11891                 goto out;
11892         } else {
11893                 /* Should be bad tid. */
11894                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11895                                 NT_STATUS_NETWORK_NAME_DELETED)) {
11896                         correct = false;
11897                         goto out;
11898                 }
11899         }
11900
11901         cli_rmdir(cli, "\\uid_reg_test");
11902
11903   out:
11904
11905         cli_shutdown(cli);
11906         return correct;
11907 }
11908
11909
11910 static const char *illegal_chars = "*\\/?<>|\":";
11911 static char force_shortname_chars[] = " +,.[];=\177";
11912
11913 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11914                              const char *mask, void *state)
11915 {
11916         struct cli_state *pcli = (struct cli_state *)state;
11917         fstring fname;
11918         NTSTATUS status = NT_STATUS_OK;
11919
11920         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11921
11922         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11923                 return NT_STATUS_OK;
11924
11925         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11926                 status = cli_rmdir(pcli, fname);
11927                 if (!NT_STATUS_IS_OK(status)) {
11928                         printf("del_fn: failed to rmdir %s\n,", fname );
11929                 }
11930         } else {
11931                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11932                 if (!NT_STATUS_IS_OK(status)) {
11933                         printf("del_fn: failed to unlink %s\n,", fname );
11934                 }
11935         }
11936         return status;
11937 }
11938
11939 struct sn_state {
11940         int matched;
11941         int i;
11942         bool val;
11943 };
11944
11945 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11946                               const char *name, void *state)
11947 {
11948         struct sn_state *s = (struct sn_state  *)state;
11949         int i = s->i;
11950
11951 #if 0
11952         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11953                 i, finfo->name, finfo->short_name);
11954 #endif
11955
11956         if (strchr(force_shortname_chars, i)) {
11957                 if (!finfo->short_name) {
11958                         /* Shortname not created when it should be. */
11959                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11960                                 __location__, finfo->name, i);
11961                         s->val = true;
11962                 }
11963         } else if (finfo->short_name){
11964                 /* Shortname created when it should not be. */
11965                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11966                         __location__, finfo->short_name, finfo->name);
11967                 s->val = true;
11968         }
11969         s->matched += 1;
11970         return NT_STATUS_OK;
11971 }
11972
11973 static bool run_shortname_test(int dummy)
11974 {
11975         static struct cli_state *cli;
11976         bool correct = True;
11977         int i;
11978         struct sn_state s;
11979         char fname[40];
11980         NTSTATUS status;
11981
11982         printf("starting shortname test\n");
11983
11984         if (!torture_open_connection(&cli, 0)) {
11985                 return False;
11986         }
11987
11988         smbXcli_conn_set_sockopt(cli->conn, sockops);
11989
11990         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11991         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11992         cli_rmdir(cli, "\\shortname");
11993
11994         status = cli_mkdir(cli, "\\shortname");
11995         if (!NT_STATUS_IS_OK(status)) {
11996                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11997                         __location__, nt_errstr(status));
11998                 correct = false;
11999                 goto out;
12000         }
12001
12002         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12003                 correct = false;
12004                 goto out;
12005         }
12006         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12007                 correct = false;
12008                 goto out;
12009         }
12010
12011         s.val = false;
12012
12013         for (i = 32; i < 128; i++) {
12014                 uint16_t fnum = (uint16_t)-1;
12015
12016                 s.i = i;
12017
12018                 if (strchr(illegal_chars, i)) {
12019                         continue;
12020                 }
12021                 fname[15] = i;
12022
12023                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12024                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12025                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12026                 if (!NT_STATUS_IS_OK(status)) {
12027                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12028                                 __location__, fname, nt_errstr(status));
12029                         correct = false;
12030                         goto out;
12031                 }
12032                 cli_close(cli, fnum);
12033
12034                 s.matched = 0;
12035                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12036                                   shortname_list_fn, &s);
12037                 if (s.matched != 1) {
12038                         d_printf("(%s) failed to list %s: %s\n",
12039                                 __location__, fname, nt_errstr(status));
12040                         correct = false;
12041                         goto out;
12042                 }
12043
12044                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12045                 if (!NT_STATUS_IS_OK(status)) {
12046                         d_printf("(%s) failed to delete %s: %s\n",
12047                                 __location__, fname, nt_errstr(status));
12048                         correct = false;
12049                         goto out;
12050                 }
12051
12052                 if (s.val) {
12053                         correct = false;
12054                         goto out;
12055                 }
12056         }
12057
12058   out:
12059
12060         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12061         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12062         cli_rmdir(cli, "\\shortname");
12063         torture_close_connection(cli);
12064         return correct;
12065 }
12066
12067 TLDAPRC callback_code;
12068
12069 static void pagedsearch_cb(struct tevent_req *req)
12070 {
12071         TLDAPRC rc;
12072         struct tldap_message *msg;
12073         char *dn;
12074
12075         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12076         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12077                 d_printf("tldap_search_paged_recv failed: %s\n",
12078                          tldap_rc2string(rc));
12079                 callback_code = rc;
12080                 return;
12081         }
12082         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12083                 TALLOC_FREE(msg);
12084                 return;
12085         }
12086         if (!tldap_entry_dn(msg, &dn)) {
12087                 d_printf("tldap_entry_dn failed\n");
12088                 return;
12089         }
12090         d_printf("%s\n", dn);
12091         TALLOC_FREE(msg);
12092 }
12093
12094 enum tldap_extended_val {
12095         EXTENDED_ZERO = 0,
12096         EXTENDED_ONE = 1,
12097         EXTENDED_NONE = 2,
12098 };
12099
12100 /*
12101  * Construct an extended dn control with either no value, 0 or 1
12102  *
12103  * No value and 0 are equivalent (non-hyphenated GUID)
12104  * 1 has the hyphenated GUID
12105  */
12106 static struct tldap_control *
12107 tldap_build_extended_control(enum tldap_extended_val val)
12108 {
12109         struct tldap_control empty_control;
12110         struct asn1_data *data;
12111
12112         ZERO_STRUCT(empty_control);
12113
12114         if (val != EXTENDED_NONE) {
12115                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12116
12117                 if (!data) {
12118                         return NULL;
12119                 }
12120
12121                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12122                         return NULL;
12123                 }
12124
12125                 if (!asn1_write_Integer(data, (int)val)) {
12126                         return NULL;
12127                 }
12128
12129                 if (!asn1_pop_tag(data)) {
12130                         return NULL;
12131                 }
12132
12133                 if (!asn1_blob(data, &empty_control.value)) {
12134                         return NULL;
12135                 }
12136         }
12137
12138         empty_control.oid = "1.2.840.113556.1.4.529";
12139         empty_control.critical = true;
12140
12141         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12142
12143 }
12144
12145 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12146                                       enum tldap_extended_val control_val)
12147 {
12148         struct tldap_control *control = tldap_build_extended_control(control_val);
12149         char *dn = NULL;
12150         struct tldap_message **msg;
12151         TLDAPRC rc;
12152
12153         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12154                           "(objectClass=*)", NULL, 0, 0,
12155                           control, 1, NULL,
12156                           0, 0, 0, 0, talloc_tos(), &msg);
12157         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12158                 d_printf("tldap_search for domain DN failed: %s\n",
12159                          tldap_errstr(talloc_tos(), ld, rc));
12160                 return false;
12161         }
12162
12163         if (!tldap_entry_dn(msg[0], &dn)) {
12164                 d_printf("tldap_search domain DN fetch failed: %s\n",
12165                          tldap_errstr(talloc_tos(), ld, rc));
12166                 return false;
12167         }
12168
12169         d_printf("%s\n", dn);
12170         {
12171                 uint32_t time_low;
12172                 uint32_t time_mid, time_hi_and_version;
12173                 uint32_t clock_seq[2];
12174                 uint32_t node[6];
12175                 char next;
12176
12177                 switch (control_val) {
12178                 case EXTENDED_NONE:
12179                 case EXTENDED_ZERO:
12180                         /*
12181                          * When reading GUIDs with hyphens, scanf will treat
12182                          * hyphen as a hex character (and counts as part of the
12183                          * width). This creates leftover GUID string which we
12184                          * check will for with 'next' and closing '>'.
12185                          */
12186                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12187                                          &time_low, &time_mid,
12188                                          &time_hi_and_version, &clock_seq[0],
12189                                          &clock_seq[1], &node[0], &node[1],
12190                                          &node[2], &node[3], &node[4],
12191                                          &node[5], &next)) {
12192                                 /* This GUID is good */
12193                         } else {
12194                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12195                                 return false;
12196                         }
12197
12198                         break;
12199                 case EXTENDED_ONE:
12200                         if (12 == sscanf(dn,
12201                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12202                                          &time_low, &time_mid,
12203                                          &time_hi_and_version, &clock_seq[0],
12204                                          &clock_seq[1], &node[0], &node[1],
12205                                          &node[2], &node[3], &node[4],
12206                                          &node[5], &next)) {
12207                                 /* This GUID is good */
12208                         } else {
12209                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12210                                 return false;
12211                         }
12212
12213                         break;
12214                 default:
12215                         return false;
12216                 }
12217         }
12218
12219         return true;
12220 }
12221
12222 static bool run_tldap(int dummy)
12223 {
12224         struct tldap_context *ld;
12225         int fd;
12226         TLDAPRC rc;
12227         NTSTATUS status;
12228         struct sockaddr_storage addr;
12229         struct tevent_context *ev;
12230         struct tevent_req *req;
12231         char *basedn;
12232         const char *filter;
12233
12234         if (!resolve_name(host, &addr, 0, false)) {
12235                 d_printf("could not find host %s\n", host);
12236                 return false;
12237         }
12238         status = open_socket_out(&addr, 389, 9999, &fd);
12239         if (!NT_STATUS_IS_OK(status)) {
12240                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12241                 return false;
12242         }
12243
12244         ld = tldap_context_create(talloc_tos(), fd);
12245         if (ld == NULL) {
12246                 close(fd);
12247                 d_printf("tldap_context_create failed\n");
12248                 return false;
12249         }
12250
12251         rc = tldap_fetch_rootdse(ld);
12252         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12253                 d_printf("tldap_fetch_rootdse failed: %s\n",
12254                          tldap_errstr(talloc_tos(), ld, rc));
12255                 return false;
12256         }
12257
12258         basedn = tldap_talloc_single_attribute(
12259                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12260         if (basedn == NULL) {
12261                 d_printf("no defaultNamingContext\n");
12262                 return false;
12263         }
12264         d_printf("defaultNamingContext: %s\n", basedn);
12265
12266         ev = samba_tevent_context_init(talloc_tos());
12267         if (ev == NULL) {
12268                 d_printf("tevent_context_init failed\n");
12269                 return false;
12270         }
12271
12272         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12273                                loadparm_init_s3(talloc_tos(),
12274                                                 loadparm_s3_helpers()),
12275                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12276
12277         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12278                 d_printf("tldap_gensec_bind failed\n");
12279                 return false;
12280         }
12281
12282         callback_code = TLDAP_SUCCESS;
12283
12284         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12285                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12286                                       NULL, 0, 0,
12287                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12288         if (req == NULL) {
12289                 d_printf("tldap_search_paged_send failed\n");
12290                 return false;
12291         }
12292         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12293
12294         tevent_req_poll(req, ev);
12295
12296         TALLOC_FREE(req);
12297
12298         rc = callback_code;
12299
12300         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12301                 d_printf("tldap_search with paging failed: %s\n",
12302                          tldap_errstr(talloc_tos(), ld, rc));
12303                 return false;
12304         }
12305
12306         /* test search filters against rootDSE */
12307         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12308                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12309
12310         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12311                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12312                           talloc_tos(), NULL);
12313         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12314                 d_printf("tldap_search with complex filter failed: %s\n",
12315                          tldap_errstr(talloc_tos(), ld, rc));
12316                 return false;
12317         }
12318
12319         /*
12320          * Tests to check for regression of:
12321          *
12322          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12323          *
12324          * TLDAP used here to pick apart the original string DN (with GUID)
12325          */
12326         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12327                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12328                          tldap_errstr(talloc_tos(), ld, rc));
12329                 return false;
12330         }
12331         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12332                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12333                          tldap_errstr(talloc_tos(), ld, rc));
12334                 return false;
12335         }
12336         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12337                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12338                          tldap_errstr(talloc_tos(), ld, rc));
12339                 return false;
12340         }
12341
12342         TALLOC_FREE(ld);
12343         return true;
12344 }
12345
12346 /* Torture test to ensure no regression of :
12347 https://bugzilla.samba.org/show_bug.cgi?id=7084
12348 */
12349
12350 static bool run_dir_createtime(int dummy)
12351 {
12352         struct cli_state *cli;
12353         const char *dname = "\\testdir_createtime";
12354         const char *fname = "\\testdir_createtime\\testfile";
12355         NTSTATUS status;
12356         struct timespec create_time;
12357         struct timespec create_time1;
12358         uint16_t fnum;
12359         bool ret = false;
12360         uint64_t ino;
12361
12362         if (!torture_open_connection(&cli, 0)) {
12363                 return false;
12364         }
12365
12366         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12367                 /* Ensure ino is zero, SMB2 gets a real one. */
12368                 ino = 0;
12369         } else {
12370                 /* Ensure ino is -1, SMB1 never gets a real one. */
12371                 ino = (uint64_t)-1;
12372         }
12373
12374         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12375         cli_rmdir(cli, dname);
12376
12377         status = cli_mkdir(cli, dname);
12378         if (!NT_STATUS_IS_OK(status)) {
12379                 printf("mkdir failed: %s\n", nt_errstr(status));
12380                 goto out;
12381         }
12382
12383         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12384                                 NULL, NULL, &ino);
12385         if (!NT_STATUS_IS_OK(status)) {
12386                 printf("cli_qpathinfo2 returned %s\n",
12387                        nt_errstr(status));
12388                 goto out;
12389         }
12390
12391         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12392                 /* SMB2 should always return an inode. */
12393                 if (ino == 0) {
12394                         printf("SMB2 bad inode (0)\n");
12395                         goto out;
12396                 }
12397         } else {
12398                 /* SMB1 must always return zero here. */
12399                 if (ino != 0) {
12400                         printf("SMB1 bad inode (!0)\n");
12401                         goto out;
12402                 }
12403         }
12404
12405         /* Sleep 3 seconds, then create a file. */
12406         sleep(3);
12407
12408         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12409                          DENY_NONE, &fnum);
12410         if (!NT_STATUS_IS_OK(status)) {
12411                 printf("cli_openx failed: %s\n", nt_errstr(status));
12412                 goto out;
12413         }
12414
12415         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12416                                 NULL, NULL, NULL);
12417         if (!NT_STATUS_IS_OK(status)) {
12418                 printf("cli_qpathinfo2 (2) returned %s\n",
12419                        nt_errstr(status));
12420                 goto out;
12421         }
12422
12423         if (timespec_compare(&create_time1, &create_time)) {
12424                 printf("run_dir_createtime: create time was updated (error)\n");
12425         } else {
12426                 printf("run_dir_createtime: create time was not updated (correct)\n");
12427                 ret = true;
12428         }
12429
12430   out:
12431
12432         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12433         cli_rmdir(cli, dname);
12434         if (!torture_close_connection(cli)) {
12435                 ret = false;
12436         }
12437         return ret;
12438 }
12439
12440
12441 static bool run_streamerror(int dummy)
12442 {
12443         struct cli_state *cli;
12444         const char *dname = "\\testdir_streamerror";
12445         const char *streamname =
12446                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12447         NTSTATUS status;
12448         time_t change_time, access_time, write_time;
12449         off_t size;
12450         uint16_t fnum;
12451         uint32_t attr;
12452         bool ret = true;
12453
12454         if (!torture_open_connection(&cli, 0)) {
12455                 return false;
12456         }
12457
12458         torture_deltree(cli, dname);
12459
12460         status = cli_mkdir(cli, dname);
12461         if (!NT_STATUS_IS_OK(status)) {
12462                 printf("mkdir failed: %s\n", nt_errstr(status));
12463                 return false;
12464         }
12465
12466         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12467                                 &write_time, &size, &attr);
12468         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12469                 printf("pathinfo returned %s, expected "
12470                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12471                        nt_errstr(status));
12472                 ret = false;
12473         }
12474
12475         status = cli_ntcreate(cli, streamname, 0x16,
12476                               FILE_READ_DATA|FILE_READ_EA|
12477                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12478                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12479                               FILE_OPEN, 0, 0, &fnum, NULL);
12480
12481         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12482                 printf("ntcreate returned %s, expected "
12483                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12484                        nt_errstr(status));
12485                 ret = false;
12486         }
12487
12488
12489         cli_rmdir(cli, dname);
12490         return ret;
12491 }
12492
12493 struct pidtest_state {
12494         bool success;
12495         uint16_t vwv[1];
12496         DATA_BLOB data;
12497 };
12498
12499 static void pid_echo_done(struct tevent_req *subreq);
12500
12501 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12502                         struct tevent_context *ev,
12503                         struct cli_state *cli)
12504 {
12505         struct tevent_req *req, *subreq;
12506         struct pidtest_state *state;
12507
12508         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12509         if (req == NULL) {
12510                 return NULL;
12511         }
12512
12513         SSVAL(state->vwv, 0, 1);
12514         state->data = data_blob_const("hello", 5);
12515
12516         subreq = smb1cli_req_send(state,
12517                                 ev,
12518                                 cli->conn,
12519                                 SMBecho,
12520                                 0, 0, /* *_flags */
12521                                 0, 0, /* *_flags2 */
12522                                 cli->timeout,
12523                                 0xDEADBEEF, /* pid */
12524                                 NULL, /* tcon */
12525                                 NULL, /* session */
12526                                 ARRAY_SIZE(state->vwv), state->vwv,
12527                                 state->data.length, state->data.data);
12528
12529         if (tevent_req_nomem(subreq, req)) {
12530                 return tevent_req_post(req, ev);
12531         }
12532         tevent_req_set_callback(subreq, pid_echo_done, req);
12533         return req;
12534 }
12535
12536 static void pid_echo_done(struct tevent_req *subreq)
12537 {
12538         struct tevent_req *req = tevent_req_callback_data(
12539                 subreq, struct tevent_req);
12540         struct pidtest_state *state = tevent_req_data(
12541                 req, struct pidtest_state);
12542         NTSTATUS status;
12543         uint32_t num_bytes;
12544         uint8_t *bytes = NULL;
12545         struct iovec *recv_iov = NULL;
12546         uint8_t *phdr = NULL;
12547         uint16_t pidlow = 0;
12548         uint16_t pidhigh = 0;
12549         struct smb1cli_req_expected_response expected[] = {
12550         {
12551                 .status = NT_STATUS_OK,
12552                 .wct    = 1,
12553         },
12554         };
12555
12556         status = smb1cli_req_recv(subreq, state,
12557                                 &recv_iov,
12558                                 &phdr,
12559                                 NULL, /* pwct */
12560                                 NULL, /* pvwv */
12561                                 NULL, /* pvwv_offset */
12562                                 &num_bytes,
12563                                 &bytes,
12564                                 NULL, /* pbytes_offset */
12565                                 NULL, /* pinbuf */
12566                                 expected, ARRAY_SIZE(expected));
12567
12568         TALLOC_FREE(subreq);
12569
12570         if (!NT_STATUS_IS_OK(status)) {
12571                 tevent_req_nterror(req, status);
12572                 return;
12573         }
12574
12575         if (num_bytes != state->data.length) {
12576                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12577                 return;
12578         }
12579
12580         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12581                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12582                 return;
12583         }
12584
12585         /* Check pid low/high == DEADBEEF */
12586         pidlow = SVAL(phdr, HDR_PID);
12587         if (pidlow != 0xBEEF){
12588                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12589                         (unsigned int)pidlow);
12590                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12591                 return;
12592         }
12593         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12594         if (pidhigh != 0xDEAD){
12595                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12596                         (unsigned int)pidhigh);
12597                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12598                 return;
12599         }
12600
12601         tevent_req_done(req);
12602 }
12603
12604 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12605 {
12606         return tevent_req_simple_recv_ntstatus(req);
12607 }
12608
12609 static bool run_pidhigh(int dummy)
12610 {
12611         bool success = false;
12612         struct cli_state *cli = NULL;
12613         NTSTATUS status;
12614         struct tevent_context *ev = NULL;
12615         struct tevent_req *req = NULL;
12616         TALLOC_CTX *frame = talloc_stackframe();
12617
12618         printf("starting pid high test\n");
12619         if (!torture_open_connection(&cli, 0)) {
12620                 return false;
12621         }
12622         smbXcli_conn_set_sockopt(cli->conn, sockops);
12623
12624         ev = samba_tevent_context_init(frame);
12625         if (ev == NULL) {
12626                 goto fail;
12627         }
12628
12629         req = pid_echo_send(frame, ev, cli);
12630         if (req == NULL) {
12631                 goto fail;
12632         }
12633
12634         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12635                 goto fail;
12636         }
12637
12638         status = pid_echo_recv(req);
12639         if (NT_STATUS_IS_OK(status)) {
12640                 printf("pid high test ok\n");
12641                 success = true;
12642         }
12643
12644  fail:
12645
12646         TALLOC_FREE(frame);
12647         torture_close_connection(cli);
12648         return success;
12649 }
12650
12651 /*
12652   Test Windows open on a bad POSIX symlink.
12653  */
12654 static bool run_symlink_open_test(int dummy)
12655 {
12656         static struct cli_state *cli;
12657         const char *fname = "non_existant_file";
12658         const char *sname = "dangling_symlink";
12659         uint16_t fnum = (uint16_t)-1;
12660         bool correct = false;
12661         NTSTATUS status;
12662         TALLOC_CTX *frame = NULL;
12663
12664         frame = talloc_stackframe();
12665
12666         printf("Starting Windows bad symlink open test\n");
12667
12668         if (!torture_open_connection(&cli, 0)) {
12669                 TALLOC_FREE(frame);
12670                 return false;
12671         }
12672
12673         smbXcli_conn_set_sockopt(cli->conn, sockops);
12674
12675         status = torture_setup_unix_extensions(cli);
12676         if (!NT_STATUS_IS_OK(status)) {
12677                 TALLOC_FREE(frame);
12678                 return false;
12679         }
12680
12681         /* Ensure nothing exists. */
12682         cli_setatr(cli, fname, 0, 0);
12683         cli_posix_unlink(cli, fname);
12684         cli_setatr(cli, sname, 0, 0);
12685         cli_posix_unlink(cli, sname);
12686
12687         /* Create a symlink pointing nowhere. */
12688         status = cli_posix_symlink(cli, fname, sname);
12689         if (!NT_STATUS_IS_OK(status)) {
12690                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12691                         sname,
12692                         fname,
12693                         nt_errstr(status));
12694                 goto out;
12695         }
12696
12697         /* Now ensure that a Windows open doesn't hang. */
12698         status = cli_ntcreate(cli,
12699                         sname,
12700                         0,
12701                         FILE_READ_DATA|FILE_WRITE_DATA,
12702                         0,
12703                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12704                         FILE_OPEN_IF,
12705                         0x0,
12706                         0x0,
12707                         &fnum,
12708                         NULL);
12709
12710         /*
12711          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12712          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12713          * we use O_NOFOLLOW on the server or not.
12714          */
12715         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12716             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12717         {
12718                 correct = true;
12719         } else {
12720                 printf("cli_ntcreate of %s returned %s - should return"
12721                                 " either (%s) or (%s)\n",
12722                         sname,
12723                         nt_errstr(status),
12724                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12725                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12726                 goto out;
12727         }
12728
12729         correct = true;
12730
12731   out:
12732
12733         if (fnum != (uint16_t)-1) {
12734                 cli_close(cli, fnum);
12735                 fnum = (uint16_t)-1;
12736         }
12737
12738         cli_setatr(cli, sname, 0, 0);
12739         cli_posix_unlink(cli, sname);
12740         cli_setatr(cli, fname, 0, 0);
12741         cli_posix_unlink(cli, fname);
12742
12743         if (!torture_close_connection(cli)) {
12744                 correct = false;
12745         }
12746
12747         TALLOC_FREE(frame);
12748         return correct;
12749 }
12750
12751 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12752                                         const char *name,
12753                                         void *state)
12754 {
12755         char **mangled_name_return = (char **)state;
12756         bool is_mangled = strchr(finfo->name, '~');
12757
12758         if (is_mangled) {
12759                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12760                 if (*mangled_name_return == NULL) {
12761                         return NT_STATUS_NO_MEMORY;
12762                 }
12763         }
12764         return NT_STATUS_OK;
12765 }
12766
12767 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12768 {
12769         static struct cli_state *cli_posix = NULL;
12770         static struct cli_state *cli = NULL;
12771         uint16_t fnum = (uint16_t)-1;
12772         bool correct = false;
12773         const char *dname = "smb1_wild_mangle_unlink";
12774         const char *aname = "smb1_wild_mangle_unlink/a";
12775         const char *star_name = "smb1_wild_mangle_unlink/*";
12776         char *windows_unlink_name = NULL;
12777         char *mangled_name = NULL;
12778         NTSTATUS status;
12779
12780         printf("Starting SMB1 wild mangle unlink test\n");
12781
12782         /* Open a Windows connection. */
12783         if (!torture_open_connection(&cli, 0)) {
12784                 return false;
12785         }
12786
12787         smbXcli_conn_set_sockopt(cli->conn, sockops);
12788
12789         /* Open a POSIX connection. */
12790         if (!torture_open_connection(&cli_posix, 0)) {
12791                 goto out;
12792         }
12793
12794         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12795
12796         status = torture_setup_unix_extensions(cli_posix);
12797         if (!NT_STATUS_IS_OK(status)) {
12798                 printf("server doesn't support POSIX\n");
12799                 goto out;
12800         }
12801
12802         /* Start fresh. */
12803         torture_deltree(cli, dname);
12804
12805         /*
12806          * Create two files - 'a' and '*'.
12807          * We need POSIX extensions for this as '*'
12808          * is not a valid Windows name.
12809          */
12810
12811         status = cli_mkdir(cli, dname);
12812         if (!NT_STATUS_IS_OK(status)) {
12813                 printf("cli_mkdir of %s returned %s\n",
12814                         dname,
12815                         nt_errstr(status));
12816                 goto out;
12817         }
12818
12819         status = cli_posix_open(cli_posix,
12820                                 aname,
12821                                 O_RDWR|O_CREAT|O_EXCL,
12822                                 0660,
12823                                 &fnum);
12824         if (!NT_STATUS_IS_OK(status)) {
12825                 printf("cli_posix_open (create) of %s returned %s\n",
12826                         aname,
12827                         nt_errstr(status));
12828                 goto out;
12829         }
12830         status = cli_close(cli_posix, fnum);
12831         if (!NT_STATUS_IS_OK(status)) {
12832                 goto out;
12833         }
12834         status = cli_posix_open(cli_posix,
12835                                 star_name,
12836                                 O_RDWR|O_CREAT|O_EXCL,
12837                                 0660,
12838                                 &fnum);
12839         if (!NT_STATUS_IS_OK(status)) {
12840                 printf("cli_posix_open (create) of %s returned %s\n",
12841                         star_name,
12842                         nt_errstr(status));
12843                 goto out;
12844         }
12845         status = cli_close(cli_posix, fnum);
12846         if (!NT_STATUS_IS_OK(status)) {
12847                 goto out;
12848         }
12849
12850         status = cli_list(cli,
12851                         star_name,
12852                         0,
12853                         smb1_wild_mangle_list_fn,
12854                         &mangled_name);
12855         if (!NT_STATUS_IS_OK(status)) {
12856                 printf("cli_list of %s returned %s\n",
12857                         star_name,
12858                         nt_errstr(status));
12859                 goto out;
12860         }
12861
12862         if (mangled_name == NULL) {
12863                 goto out;
12864         }
12865
12866         printf("mangled_name = %s\n",
12867                 mangled_name);
12868
12869         /*
12870          * Try a Windows unlink with the mangled name.
12871          * This should *NOT* unlink the 'a' name.
12872          */
12873
12874         windows_unlink_name = talloc_asprintf(cli_posix,
12875                                         "%s\\%s",
12876                                         dname,
12877                                         mangled_name);
12878
12879         status = cli_unlink(cli, windows_unlink_name, 0);
12880         if (!NT_STATUS_IS_OK(status)) {
12881                 printf("cli_unlink of %s returned %s\n",
12882                         windows_unlink_name,
12883                         nt_errstr(status));
12884                 goto out;
12885         }
12886
12887         /* Does 'a' still exist ? */
12888         status = cli_posix_open(cli_posix,
12889                                 aname,
12890                                 O_RDONLY,
12891                                 0,
12892                                 &fnum);
12893         if (!NT_STATUS_IS_OK(status)) {
12894                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12895                         aname,
12896                         nt_errstr(status));
12897                 goto out;
12898         }
12899
12900         status = cli_close(cli_posix, fnum);
12901         if (!NT_STATUS_IS_OK(status)) {
12902                 goto out;
12903         }
12904
12905         correct = true;
12906
12907   out:
12908
12909         TALLOC_FREE(windows_unlink_name);
12910         TALLOC_FREE(mangled_name);
12911
12912         if (cli != NULL) {
12913                 torture_deltree(cli, dname);
12914                 torture_close_connection(cli);
12915         }
12916
12917         if (cli_posix != NULL) {
12918                 torture_close_connection(cli_posix);
12919         }
12920
12921         return correct;
12922 }
12923
12924 static bool run_smb1_wild_mangle_rename_test(int dummy)
12925 {
12926         static struct cli_state *cli_posix = NULL;
12927         static struct cli_state *cli = NULL;
12928         uint16_t fnum = (uint16_t)-1;
12929         bool correct = false;
12930         const char *dname = "smb1_wild_mangle_rename";
12931         const char *fooname = "smb1_wild_mangle_rename/foo";
12932         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12933         const char *wild_name = "smb1_wild_mangle_rename/*";
12934         char *windows_rename_src = NULL;
12935         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12936         char *mangled_name = NULL;
12937         NTSTATUS status;
12938
12939         printf("Starting SMB1 wild mangle rename test\n");
12940
12941         if (!torture_open_connection(&cli_posix, 0)) {
12942                 return false;
12943         }
12944
12945         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12946
12947         status = torture_setup_unix_extensions(cli_posix);
12948         if (!NT_STATUS_IS_OK(status)) {
12949                 printf("server doesn't support POSIX\n");
12950                 return false;
12951         }
12952
12953         /* Open a Windows connection. */
12954         if (!torture_open_connection(&cli, 0)) {
12955                 goto out;
12956         }
12957
12958         smbXcli_conn_set_sockopt(cli->conn, sockops);
12959
12960         /* Ensure we start from fresh. */
12961         torture_deltree(cli, dname);
12962
12963         /*
12964          * Create two files - 'foo' and 'fo*'.
12965          * We need POSIX extensions for this as 'fo*'
12966          * is not a valid Windows name.
12967          */
12968
12969         status = cli_posix_mkdir(cli_posix, dname, 0770);
12970         if (!NT_STATUS_IS_OK(status)) {
12971                 printf("cli_posix_mkdir of %s returned %s\n",
12972                         dname,
12973                         nt_errstr(status));
12974                 goto out;
12975         }
12976
12977         status = cli_posix_open(cli_posix,
12978                                 fooname,
12979                                 O_RDWR|O_CREAT|O_EXCL,
12980                                 0660,
12981                                 &fnum);
12982         if (!NT_STATUS_IS_OK(status)) {
12983                 printf("cli_posix_open (create) of %s returned %s\n",
12984                         fooname,
12985                         nt_errstr(status));
12986                 goto out;
12987         }
12988         status = cli_close(cli_posix, fnum);
12989         if (!NT_STATUS_IS_OK(status)) {
12990                 goto out;
12991         }
12992         status = cli_posix_open(cli_posix,
12993                                 foostar_name,
12994                                 O_RDWR|O_CREAT|O_EXCL,
12995                                 0660,
12996                                 &fnum);
12997         if (!NT_STATUS_IS_OK(status)) {
12998                 printf("cli_posix_open (create) of %s returned %s\n",
12999                         foostar_name,
13000                         nt_errstr(status));
13001                 goto out;
13002         }
13003         status = cli_close(cli_posix, fnum);
13004         if (!NT_STATUS_IS_OK(status)) {
13005                 goto out;
13006         }
13007
13008         /*
13009          * Get the mangled name. We can re-use the
13010          * previous smb1_wild_mangle_list_fn for this.
13011          */
13012
13013         status = cli_list(cli,
13014                         wild_name,
13015                         0,
13016                         smb1_wild_mangle_list_fn,
13017                         &mangled_name);
13018         if (!NT_STATUS_IS_OK(status)) {
13019                 printf("cli_list of %s returned %s\n",
13020                         wild_name,
13021                         nt_errstr(status));
13022                 goto out;
13023         }
13024
13025         if (mangled_name == NULL) {
13026                 goto out;
13027         }
13028
13029         printf("mangled_name = %s\n",
13030                 mangled_name);
13031
13032         /*
13033          * Try a Windows rename with the mangled name.
13034          * This should *NOT* rename the 'foo' name.
13035          */
13036
13037         windows_rename_src = talloc_asprintf(cli_posix,
13038                                         "%s\\%s",
13039                                         dname,
13040                                         mangled_name);
13041
13042         status = cli_rename(cli,
13043                         windows_rename_src,
13044                         windows_rename_dst,
13045                         false);
13046         if (!NT_STATUS_IS_OK(status)) {
13047                 printf("cli_rename of %s -> %s returned %s\n",
13048                         windows_rename_src,
13049                         windows_rename_dst,
13050                         nt_errstr(status));
13051                 goto out;
13052         }
13053
13054         /* Does 'foo' still exist ? */
13055         status = cli_posix_open(cli_posix,
13056                                 fooname,
13057                                 O_RDONLY,
13058                                 0,
13059                                 &fnum);
13060         if (!NT_STATUS_IS_OK(status)) {
13061                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13062                         fooname,
13063                         nt_errstr(status));
13064                 goto out;
13065         }
13066
13067         status = cli_close(cli_posix, fnum);
13068         if (!NT_STATUS_IS_OK(status)) {
13069                 goto out;
13070         }
13071
13072         correct = true;
13073
13074   out:
13075
13076         TALLOC_FREE(mangled_name);
13077         TALLOC_FREE(windows_rename_src);
13078
13079         if (cli != NULL) {
13080                 torture_deltree(cli, dname);
13081                 torture_close_connection(cli);
13082         }
13083
13084         torture_close_connection(cli_posix);
13085
13086         return correct;
13087 }
13088
13089 /*
13090  * Only testing minimal time strings, as the others
13091  * need (locale-dependent) guessing at what strftime does and
13092  * even may differ in builds.
13093  */
13094 static bool timesubst_test(void)
13095 {
13096         TALLOC_CTX *ctx = NULL;
13097         /* Sa 23. Dez 04:33:20 CET 2017 */
13098         const struct timeval tv = { 1514000000, 123 };
13099         const char* expect_minimal = "20171223_033320";
13100         const char* expect_minus   = "20171223_033320_000123";
13101         char *s;
13102         char *env_tz, *orig_tz = NULL;
13103         bool result = true;
13104
13105         ctx = talloc_new(NULL);
13106
13107         env_tz = getenv("TZ");
13108         if(env_tz) {
13109                 orig_tz = talloc_strdup(ctx, env_tz);
13110         }
13111         setenv("TZ", "UTC", 1);
13112
13113         s = minimal_timeval_string(ctx, &tv, false);
13114
13115         if(!s || strcmp(s, expect_minimal)) {
13116                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13117                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13118                 result = false;
13119         }
13120         TALLOC_FREE(s);
13121         s = minimal_timeval_string(ctx, &tv, true);
13122         if(!s || strcmp(s, expect_minus)) {
13123                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13124                        "[%s]\n", s ? s : "<nil>", expect_minus);
13125                 result = false;
13126         }
13127         TALLOC_FREE(s);
13128
13129         if(orig_tz) {
13130                 setenv("TZ", orig_tz, 1);
13131         }
13132
13133         TALLOC_FREE(ctx);
13134         return result;
13135 }
13136
13137 static bool run_local_substitute(int dummy)
13138 {
13139         bool ok = true;
13140
13141         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13142         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13143         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13144         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13145         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13146         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13147         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13148         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13149         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13150         /* Substitution depends on current time, so better test the underlying
13151            formatting function. At least covers %t. */
13152         ok &= timesubst_test();
13153
13154         /* Different captialization rules in sub_basic... */
13155
13156         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13157                        "blaDOM") == 0);
13158
13159         return ok;
13160 }
13161
13162 static bool run_local_base64(int dummy)
13163 {
13164         int i;
13165         bool ret = true;
13166
13167         for (i=1; i<2000; i++) {
13168                 DATA_BLOB blob1, blob2;
13169                 char *b64;
13170
13171                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13172                 blob1.length = i;
13173                 generate_random_buffer(blob1.data, blob1.length);
13174
13175                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13176                 if (b64 == NULL) {
13177                         d_fprintf(stderr, "base64_encode_data_blob failed "
13178                                   "for %d bytes\n", i);
13179                         ret = false;
13180                 }
13181                 blob2 = base64_decode_data_blob(b64);
13182                 TALLOC_FREE(b64);
13183
13184                 if (data_blob_cmp(&blob1, &blob2)) {
13185                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13186                                   "bytes\n", i);
13187                         ret = false;
13188                 }
13189                 TALLOC_FREE(blob1.data);
13190                 data_blob_free(&blob2);
13191         }
13192         return ret;
13193 }
13194
13195 static void parse_fn(const struct gencache_timeout *t,
13196                      DATA_BLOB blob,
13197                      void *private_data)
13198 {
13199         return;
13200 }
13201
13202 static bool run_local_gencache(int dummy)
13203 {
13204         char *val;
13205         time_t tm;
13206         DATA_BLOB blob;
13207         char v;
13208         struct memcache *mem;
13209         int i;
13210
13211         mem = memcache_init(NULL, 0);
13212         if (mem == NULL) {
13213                 d_printf("%s: memcache_init failed\n", __location__);
13214                 return false;
13215         }
13216         memcache_set_global(mem);
13217
13218         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13219                 d_printf("%s: gencache_set() failed\n", __location__);
13220                 return False;
13221         }
13222
13223         if (!gencache_get("foo", NULL, NULL, NULL)) {
13224                 d_printf("%s: gencache_get() failed\n", __location__);
13225                 return False;
13226         }
13227
13228         for (i=0; i<1000000; i++) {
13229                 gencache_parse("foo", parse_fn, NULL);
13230         }
13231
13232         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13233                 d_printf("%s: gencache_get() failed\n", __location__);
13234                 return False;
13235         }
13236         TALLOC_FREE(val);
13237
13238         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13239                 d_printf("%s: gencache_get() failed\n", __location__);
13240                 return False;
13241         }
13242
13243         if (strcmp(val, "bar") != 0) {
13244                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13245                          __location__, val, "bar");
13246                 TALLOC_FREE(val);
13247                 return False;
13248         }
13249
13250         TALLOC_FREE(val);
13251
13252         if (!gencache_del("foo")) {
13253                 d_printf("%s: gencache_del() failed\n", __location__);
13254                 return False;
13255         }
13256         if (gencache_del("foo")) {
13257                 d_printf("%s: second gencache_del() succeeded\n",
13258                          __location__);
13259                 return False;
13260         }
13261
13262         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13263                 d_printf("%s: gencache_get() on deleted entry "
13264                          "succeeded\n", __location__);
13265                 return False;
13266         }
13267
13268         blob = data_blob_string_const_null("bar");
13269         tm = time(NULL) + 60;
13270
13271         if (!gencache_set_data_blob("foo", blob, tm)) {
13272                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13273                 return False;
13274         }
13275
13276         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13277                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13278                 return False;
13279         }
13280
13281         if (strcmp((const char *)blob.data, "bar") != 0) {
13282                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13283                          __location__, (const char *)blob.data, "bar");
13284                 data_blob_free(&blob);
13285                 return False;
13286         }
13287
13288         data_blob_free(&blob);
13289
13290         if (!gencache_del("foo")) {
13291                 d_printf("%s: gencache_del() failed\n", __location__);
13292                 return False;
13293         }
13294         if (gencache_del("foo")) {
13295                 d_printf("%s: second gencache_del() succeeded\n",
13296                          __location__);
13297                 return False;
13298         }
13299
13300         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13301                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13302                          "succeeded\n", __location__);
13303                 return False;
13304         }
13305
13306         v = 1;
13307         blob.data = (uint8_t *)&v;
13308         blob.length = sizeof(v);
13309
13310         if (!gencache_set_data_blob("blob", blob, tm)) {
13311                 d_printf("%s: gencache_set_data_blob() failed\n",
13312                          __location__);
13313                 return false;
13314         }
13315         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13316                 d_printf("%s: gencache_get succeeded\n", __location__);
13317                 return false;
13318         }
13319
13320         return True;
13321 }
13322
13323 static bool rbt_testflags(struct db_context *db, const char *key,
13324                           const char *value)
13325 {
13326         bool ret = false;
13327         NTSTATUS status;
13328         struct db_record *rec;
13329
13330         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13331         if (rec == NULL) {
13332                 d_fprintf(stderr, "fetch_locked failed\n");
13333                 goto done;
13334         }
13335
13336         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13337         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13338                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13339                           nt_errstr(status));
13340                 goto done;
13341         }
13342
13343         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13344                                      TDB_INSERT);
13345         if (!NT_STATUS_IS_OK(status)) {
13346                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13347                           nt_errstr(status));
13348                 goto done;
13349         }
13350
13351         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13352         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13353                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13354                           nt_errstr(status));
13355                 goto done;
13356         }
13357
13358         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13359         if (!NT_STATUS_IS_OK(status)) {
13360                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13361                           nt_errstr(status));
13362                 goto done;
13363         }
13364
13365         ret = true;
13366 done:
13367         TALLOC_FREE(rec);
13368         return ret;
13369 }
13370
13371 static bool rbt_testval(struct db_context *db, const char *key,
13372                         const char *value)
13373 {
13374         struct db_record *rec;
13375         TDB_DATA data = string_tdb_data(value);
13376         bool ret = false;
13377         NTSTATUS status;
13378         TDB_DATA dbvalue;
13379
13380         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13381         if (rec == NULL) {
13382                 d_fprintf(stderr, "fetch_locked failed\n");
13383                 goto done;
13384         }
13385         status = dbwrap_record_store(rec, data, 0);
13386         if (!NT_STATUS_IS_OK(status)) {
13387                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13388                 goto done;
13389         }
13390         TALLOC_FREE(rec);
13391
13392         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13393         if (rec == NULL) {
13394                 d_fprintf(stderr, "second fetch_locked failed\n");
13395                 goto done;
13396         }
13397
13398         dbvalue = dbwrap_record_get_value(rec);
13399         if ((dbvalue.dsize != data.dsize)
13400             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13401                 d_fprintf(stderr, "Got wrong data back\n");
13402                 goto done;
13403         }
13404
13405         ret = true;
13406  done:
13407         TALLOC_FREE(rec);
13408         return ret;
13409 }
13410
13411 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13412 {
13413         int *count2 = (int *)private_data;
13414         (*count2)++;
13415         return 0;
13416 }
13417
13418 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13419 {
13420         int *count2 = (int *)private_data;
13421         (*count2)++;
13422         dbwrap_record_delete(rec);
13423         return 0;
13424 }
13425
13426 static bool run_local_rbtree(int dummy)
13427 {
13428         struct db_context *db;
13429         bool ret = false;
13430         int i;
13431         NTSTATUS status;
13432         int count = 0;
13433         int count2 = 0;
13434
13435         db = db_open_rbt(NULL);
13436
13437         if (db == NULL) {
13438                 d_fprintf(stderr, "db_open_rbt failed\n");
13439                 return false;
13440         }
13441
13442         if (!rbt_testflags(db, "firstkey", "firstval")) {
13443                 goto done;
13444         }
13445
13446         for (i = 0; i < 999; i++) {
13447                 char key[sizeof("key-9223372036854775807")];
13448                 char value[sizeof("value-9223372036854775807")];
13449
13450                 snprintf(key, sizeof(key), "key%ld", random());
13451                 snprintf(value, sizeof(value) ,"value%ld", random());
13452
13453                 if (!rbt_testval(db, key, value)) {
13454                         goto done;
13455                 }
13456
13457                 snprintf(value, sizeof(value) ,"value%ld", random());
13458
13459                 if (!rbt_testval(db, key, value)) {
13460                         goto done;
13461                 }
13462         }
13463
13464         ret = true;
13465         count = 0; count2 = 0;
13466         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13467                                       &count2, &count);
13468         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13469         if ((count != count2) || (count != 1000)) {
13470                 ret = false;
13471         }
13472         count = 0; count2 = 0;
13473         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13474                                  &count2, &count);
13475         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13476         if ((count != count2) || (count != 1000)) {
13477                 ret = false;
13478         }
13479         count = 0; count2 = 0;
13480         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13481                                       &count2, &count);
13482         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13483         if ((count != count2) || (count != 0)) {
13484                 ret = false;
13485         }
13486
13487  done:
13488         TALLOC_FREE(db);
13489         return ret;
13490 }
13491
13492
13493 /*
13494   local test for character set functions
13495
13496   This is a very simple test for the functionality in convert_string_error()
13497  */
13498 static bool run_local_convert_string(int dummy)
13499 {
13500         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13501         const char *test_strings[2] = { "March", "M\303\244rz" };
13502         char dst[7];
13503         int i;
13504
13505         for (i=0; i<2; i++) {
13506                 const char *str = test_strings[i];
13507                 int len = strlen(str);
13508                 size_t converted_size;
13509                 bool ret;
13510
13511                 memset(dst, 'X', sizeof(dst));
13512
13513                 /* first try with real source length */
13514                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13515                                            str, len,
13516                                            dst, sizeof(dst),
13517                                            &converted_size);
13518                 if (ret != true) {
13519                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13520                         goto failed;
13521                 }
13522
13523                 if (converted_size != len) {
13524                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13525                                   str, len, (int)converted_size);
13526                         goto failed;
13527                 }
13528
13529                 if (strncmp(str, dst, converted_size) != 0) {
13530                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13531                         goto failed;
13532                 }
13533
13534                 if (strlen(str) != converted_size) {
13535                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13536                                   (int)strlen(str), (int)converted_size);
13537                         goto failed;
13538                 }
13539
13540                 if (dst[converted_size] != 'X') {
13541                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13542                         goto failed;
13543                 }
13544
13545                 /* now with srclen==-1, this causes the nul to be
13546                  * converted too */
13547                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13548                                            str, -1,
13549                                            dst, sizeof(dst),
13550                                            &converted_size);
13551                 if (ret != true) {
13552                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13553                         goto failed;
13554                 }
13555
13556                 if (converted_size != len+1) {
13557                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13558                                   str, len, (int)converted_size);
13559                         goto failed;
13560                 }
13561
13562                 if (strncmp(str, dst, converted_size) != 0) {
13563                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13564                         goto failed;
13565                 }
13566
13567                 if (len+1 != converted_size) {
13568                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13569                                   len+1, (int)converted_size);
13570                         goto failed;
13571                 }
13572
13573                 if (dst[converted_size] != 'X') {
13574                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13575                         goto failed;
13576                 }
13577
13578         }
13579
13580
13581         TALLOC_FREE(tmp_ctx);
13582         return true;
13583 failed:
13584         TALLOC_FREE(tmp_ctx);
13585         return false;
13586 }
13587
13588 static bool run_local_string_to_sid(int dummy) {
13589         struct dom_sid sid;
13590
13591         if (string_to_sid(&sid, "S--1-5-32-545")) {
13592                 printf("allowing S--1-5-32-545\n");
13593                 return false;
13594         }
13595         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13596                 printf("allowing S-1-5-32-+545\n");
13597                 return false;
13598         }
13599         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")) {
13600                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13601                 return false;
13602         }
13603         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13604                 printf("allowing S-1-5-32-545-abc\n");
13605                 return false;
13606         }
13607         if (string_to_sid(&sid, "S-300-5-32-545")) {
13608                 printf("allowing S-300-5-32-545\n");
13609                 return false;
13610         }
13611         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13612                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13613                 return false;
13614         }
13615         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13616                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13617                 return false;
13618         }
13619         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13620                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13621                 return false;
13622         }
13623         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13624                 printf("could not parse S-1-5-32-545\n");
13625                 return false;
13626         }
13627         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13628                 struct dom_sid_buf buf;
13629                 printf("mis-parsed S-1-5-32-545 as %s\n",
13630                        dom_sid_str_buf(&sid, &buf));
13631                 return false;
13632         }
13633         return true;
13634 }
13635
13636 static bool sid_to_string_test(const char *expected) {
13637         char *str;
13638         bool res = true;
13639         struct dom_sid sid;
13640
13641         if (!string_to_sid(&sid, expected)) {
13642                 printf("could not parse %s\n", expected);
13643                 return false;
13644         }
13645
13646         str = dom_sid_string(NULL, &sid);
13647         if (strcmp(str, expected)) {
13648                 printf("Comparison failed (%s != %s)\n", str, expected);
13649                 res = false;
13650         }
13651         TALLOC_FREE(str);
13652         return res;
13653 }
13654
13655 static bool run_local_sid_to_string(int dummy) {
13656         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13657                 return false;
13658         if (!sid_to_string_test("S-1-545"))
13659                 return false;
13660         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13661                 return false;
13662         return true;
13663 }
13664
13665 static bool run_local_binary_to_sid(int dummy) {
13666         ssize_t ret;
13667         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13668         static const uint8_t good_binary_sid[] = {
13669                 0x1, /* revision number */
13670                 15, /* num auths */
13671                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13672                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13673                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13674                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13675                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13676                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13677                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13678                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13679                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13680                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13681                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13682                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13683                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13684                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13685                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13686                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13687         };
13688
13689         static const uint8_t long_binary_sid[] = {
13690                 0x1, /* revision number */
13691                 15, /* num auths */
13692                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13693                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13694                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13695                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13696                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13697                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13698                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13699                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13700                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13701                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13702                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13703                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13704                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13705                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13706                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13707                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13708                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13709                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13710                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13711         };
13712
13713         static const uint8_t long_binary_sid2[] = {
13714                 0x1, /* revision number */
13715                 32, /* num auths */
13716                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13717                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13718                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13719                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13720                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13721                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13722                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13723                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13724                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13725                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13726                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13727                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13728                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13729                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13730                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13731                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13732                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13733                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13734                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13735                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13736                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13737                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13738                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13739                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13740                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13741                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13742                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13743                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13744                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13745                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13746                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13747                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13748                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13749         };
13750
13751         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13752         if (ret == -1) {
13753                 return false;
13754         }
13755         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13756         if (ret != -1) {
13757                 return false;
13758         }
13759         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13760         if (ret != -1) {
13761                 return false;
13762         }
13763         return true;
13764 }
13765
13766 /* Split a path name into filename and stream name components. Canonicalise
13767  * such that an implicit $DATA token is always explicit.
13768  *
13769  * The "specification" of this function can be found in the
13770  * run_local_stream_name() function in torture.c, I've tried those
13771  * combinations against a W2k3 server.
13772  */
13773
13774 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13775                                        char **pbase, char **pstream)
13776 {
13777         char *base = NULL;
13778         char *stream = NULL;
13779         char *sname; /* stream name */
13780         const char *stype; /* stream type */
13781
13782         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13783
13784         sname = strchr_m(fname, ':');
13785
13786         if (sname == NULL) {
13787                 if (pbase != NULL) {
13788                         base = talloc_strdup(mem_ctx, fname);
13789                         NT_STATUS_HAVE_NO_MEMORY(base);
13790                 }
13791                 goto done;
13792         }
13793
13794         if (pbase != NULL) {
13795                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13796                 NT_STATUS_HAVE_NO_MEMORY(base);
13797         }
13798
13799         sname += 1;
13800
13801         stype = strchr_m(sname, ':');
13802
13803         if (stype == NULL) {
13804                 sname = talloc_strdup(mem_ctx, sname);
13805                 stype = "$DATA";
13806         }
13807         else {
13808                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13809                         /*
13810                          * If there is an explicit stream type, so far we only
13811                          * allow $DATA. Is there anything else allowed? -- vl
13812                          */
13813                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13814                         TALLOC_FREE(base);
13815                         return NT_STATUS_OBJECT_NAME_INVALID;
13816                 }
13817                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13818                 stype += 1;
13819         }
13820
13821         if (sname == NULL) {
13822                 TALLOC_FREE(base);
13823                 return NT_STATUS_NO_MEMORY;
13824         }
13825
13826         if (sname[0] == '\0') {
13827                 /*
13828                  * no stream name, so no stream
13829                  */
13830                 goto done;
13831         }
13832
13833         if (pstream != NULL) {
13834                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13835                 if (stream == NULL) {
13836                         TALLOC_FREE(sname);
13837                         TALLOC_FREE(base);
13838                         return NT_STATUS_NO_MEMORY;
13839                 }
13840                 /*
13841                  * upper-case the type field
13842                  */
13843                 (void)strupper_m(strchr_m(stream, ':')+1);
13844         }
13845
13846  done:
13847         if (pbase != NULL) {
13848                 *pbase = base;
13849         }
13850         if (pstream != NULL) {
13851                 *pstream = stream;
13852         }
13853         return NT_STATUS_OK;
13854 }
13855
13856 static bool test_stream_name(const char *fname, const char *expected_base,
13857                              const char *expected_stream,
13858                              NTSTATUS expected_status)
13859 {
13860         NTSTATUS status;
13861         char *base = NULL;
13862         char *stream = NULL;
13863
13864         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13865         if (!NT_STATUS_EQUAL(status, expected_status)) {
13866                 goto error;
13867         }
13868
13869         if (!NT_STATUS_IS_OK(status)) {
13870                 return true;
13871         }
13872
13873         if (base == NULL) goto error;
13874
13875         if (strcmp(expected_base, base) != 0) goto error;
13876
13877         if ((expected_stream != NULL) && (stream == NULL)) goto error;
13878         if ((expected_stream == NULL) && (stream != NULL)) goto error;
13879
13880         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13881                 goto error;
13882
13883         TALLOC_FREE(base);
13884         TALLOC_FREE(stream);
13885         return true;
13886
13887  error:
13888         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13889                   fname, expected_base ? expected_base : "<NULL>",
13890                   expected_stream ? expected_stream : "<NULL>",
13891                   nt_errstr(expected_status));
13892         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13893                   base ? base : "<NULL>", stream ? stream : "<NULL>",
13894                   nt_errstr(status));
13895         TALLOC_FREE(base);
13896         TALLOC_FREE(stream);
13897         return false;
13898 }
13899
13900 static bool run_local_stream_name(int dummy)
13901 {
13902         bool ret = true;
13903
13904         ret &= test_stream_name(
13905                 "bla", "bla", NULL, NT_STATUS_OK);
13906         ret &= test_stream_name(
13907                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13908         ret &= test_stream_name(
13909                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13910         ret &= test_stream_name(
13911                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13912         ret &= test_stream_name(
13913                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13914         ret &= test_stream_name(
13915                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13916         ret &= test_stream_name(
13917                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13918         ret &= test_stream_name(
13919                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13920
13921         return ret;
13922 }
13923
13924 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13925 {
13926         if (a.length != b.length) {
13927                 printf("a.length=%d != b.length=%d\n",
13928                        (int)a.length, (int)b.length);
13929                 return false;
13930         }
13931         if (memcmp(a.data, b.data, a.length) != 0) {
13932                 printf("a.data and b.data differ\n");
13933                 return false;
13934         }
13935         return true;
13936 }
13937
13938 static bool run_local_memcache(int dummy)
13939 {
13940         struct memcache *cache;
13941         DATA_BLOB k1, k2, k3, k4, k5;
13942         DATA_BLOB d1, d3;
13943         DATA_BLOB v1, v3;
13944
13945         TALLOC_CTX *mem_ctx;
13946         char *ptr1 = NULL;
13947         char *ptr2 = NULL;
13948         char *ptr3 = NULL;
13949
13950         char *str1, *str2;
13951         size_t size1, size2;
13952         bool ret = false;
13953
13954         mem_ctx = talloc_init("foo");
13955         if (mem_ctx == NULL) {
13956                 return false;
13957         }
13958
13959         /* STAT_CACHE TESTS */
13960
13961         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13962
13963         if (cache == NULL) {
13964                 printf("memcache_init failed\n");
13965                 return false;
13966         }
13967
13968         d1 = data_blob_const("d1", 2);
13969         d3 = data_blob_const("d3", 2);
13970
13971         k1 = data_blob_const("d1", 2);
13972         k2 = data_blob_const("d2", 2);
13973         k3 = data_blob_const("d3", 2);
13974         k4 = data_blob_const("d4", 2);
13975         k5 = data_blob_const("d5", 2);
13976
13977         memcache_add(cache, STAT_CACHE, k1, d1);
13978
13979         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13980                 printf("could not find k1\n");
13981                 return false;
13982         }
13983         if (!data_blob_equal(d1, v1)) {
13984                 return false;
13985         }
13986
13987         memcache_add(cache, STAT_CACHE, k1, d3);
13988
13989         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13990                 printf("could not find replaced k1\n");
13991                 return false;
13992         }
13993         if (!data_blob_equal(d3, v3)) {
13994                 return false;
13995         }
13996
13997         TALLOC_FREE(cache);
13998
13999         /* GETWD_CACHE TESTS */
14000         str1 = talloc_strdup(mem_ctx, "string1");
14001         if (str1 == NULL) {
14002                 return false;
14003         }
14004         ptr2 = str1; /* Keep an alias for comparison. */
14005
14006         str2 = talloc_strdup(mem_ctx, "string2");
14007         if (str2 == NULL) {
14008                 return false;
14009         }
14010
14011         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14012         if (cache == NULL) {
14013                 printf("memcache_init failed\n");
14014                 return false;
14015         }
14016
14017         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14018         /* str1 == NULL now. */
14019         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14020         if (ptr1 == NULL) {
14021                 printf("could not find k2\n");
14022                 return false;
14023         }
14024         if (ptr1 != ptr2) {
14025                 printf("fetch of k2 got wrong string\n");
14026                 return false;
14027         }
14028
14029         /* Add a blob to ensure k2 gets purged. */
14030         d3 = data_blob_talloc_zero(mem_ctx, 180);
14031         memcache_add(cache, STAT_CACHE, k3, d3);
14032
14033         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14034         if (ptr2 != NULL) {
14035                 printf("Did find k2, should have been purged\n");
14036                 return false;
14037         }
14038
14039         /*
14040          * Test that talloc size also is accounted in memcache and
14041          * causes purge of other object.
14042          */
14043
14044         str1 = talloc_zero_size(mem_ctx, 100);
14045         str2 = talloc_zero_size(mem_ctx, 100);
14046
14047         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14048         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14049
14050         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14051         if (ptr3 != NULL) {
14052                 printf("Did find k4, should have been purged\n");
14053                 return false;
14054         }
14055
14056         /*
14057          * Test that adding a duplicate non-talloced
14058          * key/value on top of a talloced key/value takes account
14059          * of the talloc_freed value size.
14060          */
14061         TALLOC_FREE(cache);
14062         TALLOC_FREE(mem_ctx);
14063
14064         mem_ctx = talloc_init("key_replace");
14065         if (mem_ctx == NULL) {
14066                 return false;
14067         }
14068
14069         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14070         if (cache == NULL) {
14071                 return false;
14072         }
14073
14074         /*
14075          * Add a 100 byte talloced string. This will
14076          * store a (4 or 8 byte) pointer and record the
14077          * total talloced size.
14078          */
14079         str1 = talloc_zero_size(mem_ctx, 100);
14080         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14081         /*
14082          * Now overwrite with a small talloced
14083          * value. This should fit in the existing size
14084          * and the total talloced size should be removed
14085          * from the cache size.
14086          */
14087         str1 = talloc_zero_size(mem_ctx, 2);
14088         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14089         /*
14090          * Now store a 20 byte string. If the
14091          * total talloced size wasn't accounted for
14092          * and removed in the overwrite, then this
14093          * will evict k4.
14094          */
14095         str2 = talloc_zero_size(mem_ctx, 20);
14096         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14097
14098         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14099         if (ptr3 == NULL) {
14100                 printf("Did not find k4, should not have been purged\n");
14101                 return false;
14102         }
14103
14104         TALLOC_FREE(cache);
14105         TALLOC_FREE(mem_ctx);
14106
14107         mem_ctx = talloc_init("foo");
14108         if (mem_ctx == NULL) {
14109                 return false;
14110         }
14111
14112         cache = memcache_init(NULL, 0);
14113         if (cache == NULL) {
14114                 return false;
14115         }
14116
14117         str1 = talloc_strdup(mem_ctx, "string1");
14118         if (str1 == NULL) {
14119                 return false;
14120         }
14121         str2 = talloc_strdup(mem_ctx, "string2");
14122         if (str2 == NULL) {
14123                 return false;
14124         }
14125         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14126                             data_blob_string_const("torture"), &str1);
14127         size1 = talloc_total_size(cache);
14128
14129         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14130                             data_blob_string_const("torture"), &str2);
14131         size2 = talloc_total_size(cache);
14132
14133         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14134
14135         if (size2 > size1) {
14136                 printf("memcache leaks memory!\n");
14137                 goto fail;
14138         }
14139
14140         ret = true;
14141  fail:
14142         TALLOC_FREE(cache);
14143         return ret;
14144 }
14145
14146 static void wbclient_done(struct tevent_req *req)
14147 {
14148         wbcErr wbc_err;
14149         struct winbindd_response *wb_resp;
14150         int *i = (int *)tevent_req_callback_data_void(req);
14151
14152         wbc_err = wb_trans_recv(req, req, &wb_resp);
14153         TALLOC_FREE(req);
14154         *i += 1;
14155         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14156 }
14157
14158 static bool run_wbclient_multi_ping(int dummy)
14159 {
14160         struct tevent_context *ev;
14161         struct wb_context **wb_ctx;
14162         struct winbindd_request wb_req;
14163         bool result = false;
14164         int i, j;
14165
14166         BlockSignals(True, SIGPIPE);
14167
14168         ev = tevent_context_init(talloc_tos());
14169         if (ev == NULL) {
14170                 goto fail;
14171         }
14172
14173         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14174         if (wb_ctx == NULL) {
14175                 goto fail;
14176         }
14177
14178         ZERO_STRUCT(wb_req);
14179         wb_req.cmd = WINBINDD_PING;
14180
14181         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14182
14183         for (i=0; i<torture_nprocs; i++) {
14184                 wb_ctx[i] = wb_context_init(ev, NULL);
14185                 if (wb_ctx[i] == NULL) {
14186                         goto fail;
14187                 }
14188                 for (j=0; j<torture_numops; j++) {
14189                         struct tevent_req *req;
14190                         req = wb_trans_send(ev, ev, wb_ctx[i],
14191                                             (j % 2) == 0, &wb_req);
14192                         if (req == NULL) {
14193                                 goto fail;
14194                         }
14195                         tevent_req_set_callback(req, wbclient_done, &i);
14196                 }
14197         }
14198
14199         i = 0;
14200
14201         while (i < torture_nprocs * torture_numops) {
14202                 tevent_loop_once(ev);
14203         }
14204
14205         result = true;
14206  fail:
14207         TALLOC_FREE(ev);
14208         return result;
14209 }
14210
14211 static bool dbtrans_inc(struct db_context *db)
14212 {
14213         struct db_record *rec;
14214         uint32_t val;
14215         bool ret = false;
14216         NTSTATUS status;
14217         TDB_DATA value;
14218
14219         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14220         if (rec == NULL) {
14221                 printf(__location__ "fetch_lock failed\n");
14222                 return false;
14223         }
14224
14225         value = dbwrap_record_get_value(rec);
14226
14227         if (value.dsize != sizeof(uint32_t)) {
14228                 printf(__location__ "value.dsize = %d\n",
14229                        (int)value.dsize);
14230                 goto fail;
14231         }
14232
14233         memcpy(&val, value.dptr, sizeof(val));
14234         val += 1;
14235
14236         status = dbwrap_record_store(
14237                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14238         if (!NT_STATUS_IS_OK(status)) {
14239                 printf(__location__ "store failed: %s\n",
14240                        nt_errstr(status));
14241                 goto fail;
14242         }
14243
14244         ret = true;
14245 fail:
14246         TALLOC_FREE(rec);
14247         return ret;
14248 }
14249
14250 static bool run_local_dbtrans(int dummy)
14251 {
14252         struct db_context *db;
14253         struct db_record *rec;
14254         NTSTATUS status;
14255         uint32_t initial;
14256         int res;
14257         TDB_DATA value;
14258
14259         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14260                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14261                      DBWRAP_FLAG_NONE);
14262         if (db == NULL) {
14263                 printf("Could not open transtest.db\n");
14264                 return false;
14265         }
14266
14267         res = dbwrap_transaction_start(db);
14268         if (res != 0) {
14269                 printf(__location__ "transaction_start failed\n");
14270                 return false;
14271         }
14272
14273         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14274         if (rec == NULL) {
14275                 printf(__location__ "fetch_lock failed\n");
14276                 return false;
14277         }
14278
14279         value = dbwrap_record_get_value(rec);
14280
14281         if (value.dptr == NULL) {
14282                 initial = 0;
14283                 status = dbwrap_record_store(
14284                         rec, make_tdb_data((uint8_t *)&initial,
14285                                            sizeof(initial)),
14286                         0);
14287                 if (!NT_STATUS_IS_OK(status)) {
14288                         printf(__location__ "store returned %s\n",
14289                                nt_errstr(status));
14290                         return false;
14291                 }
14292         }
14293
14294         TALLOC_FREE(rec);
14295
14296         res = dbwrap_transaction_commit(db);
14297         if (res != 0) {
14298                 printf(__location__ "transaction_commit failed\n");
14299                 return false;
14300         }
14301
14302         while (true) {
14303                 uint32_t val, val2;
14304                 int i;
14305
14306                 res = dbwrap_transaction_start(db);
14307                 if (res != 0) {
14308                         printf(__location__ "transaction_start failed\n");
14309                         break;
14310                 }
14311
14312                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14313                 if (!NT_STATUS_IS_OK(status)) {
14314                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14315                                nt_errstr(status));
14316                         break;
14317                 }
14318
14319                 for (i=0; i<10; i++) {
14320                         if (!dbtrans_inc(db)) {
14321                                 return false;
14322                         }
14323                 }
14324
14325                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14326                 if (!NT_STATUS_IS_OK(status)) {
14327                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14328                                nt_errstr(status));
14329                         break;
14330                 }
14331
14332                 if (val2 != val + 10) {
14333                         printf(__location__ "val=%d, val2=%d\n",
14334                                (int)val, (int)val2);
14335                         break;
14336                 }
14337
14338                 printf("val2=%d\r", val2);
14339
14340                 res = dbwrap_transaction_commit(db);
14341                 if (res != 0) {
14342                         printf(__location__ "transaction_commit failed\n");
14343                         break;
14344                 }
14345         }
14346
14347         TALLOC_FREE(db);
14348         return true;
14349 }
14350
14351 /*
14352  * Just a dummy test to be run under a debugger. There's no real way
14353  * to inspect the tevent_poll specific function from outside of
14354  * tevent_poll.c.
14355  */
14356
14357 static bool run_local_tevent_poll(int dummy)
14358 {
14359         struct tevent_context *ev;
14360         struct tevent_fd *fd1, *fd2;
14361         bool result = false;
14362
14363         ev = tevent_context_init_byname(NULL, "poll");
14364         if (ev == NULL) {
14365                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14366                 goto fail;
14367         }
14368
14369         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14370         if (fd1 == NULL) {
14371                 d_fprintf(stderr, "tevent_add_fd failed\n");
14372                 goto fail;
14373         }
14374         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14375         if (fd2 == NULL) {
14376                 d_fprintf(stderr, "tevent_add_fd failed\n");
14377                 goto fail;
14378         }
14379         TALLOC_FREE(fd2);
14380
14381         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14382         if (fd2 == NULL) {
14383                 d_fprintf(stderr, "tevent_add_fd failed\n");
14384                 goto fail;
14385         }
14386
14387         result = true;
14388 fail:
14389         TALLOC_FREE(ev);
14390         return result;
14391 }
14392
14393 static bool run_local_hex_encode_buf(int dummy)
14394 {
14395         char buf[17];
14396         uint8_t src[8];
14397         size_t i;
14398
14399         for (i=0; i<sizeof(src); i++) {
14400                 src[i] = i;
14401         }
14402         hex_encode_buf(buf, src, sizeof(src));
14403         if (strcmp(buf, "0001020304050607") != 0) {
14404                 return false;
14405         }
14406         hex_encode_buf(buf, NULL, 0);
14407         if (buf[0] != '\0') {
14408                 return false;
14409         }
14410         return true;
14411 }
14412
14413 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14414         "0.0.0.0",
14415         "::0",
14416         "1.2.3.1",
14417         "0.0.0.0",
14418         "0.0.0.0",
14419         "1.2.3.2",
14420         "1.2.3.3",
14421         "1.2.3.4",
14422         "1.2.3.5",
14423         "::0",
14424         "1.2.3.6",
14425         "1.2.3.7",
14426         "::0",
14427         "::0",
14428         "::0",
14429         "1.2.3.8",
14430         "1.2.3.9",
14431         "1.2.3.10",
14432         "1.2.3.11",
14433         "1.2.3.12",
14434         "1.2.3.13",
14435         "1001:1111:1111:1000:0:1111:1111:1111",
14436         "1.2.3.1",
14437         "1.2.3.2",
14438         "1.2.3.3",
14439         "1.2.3.12",
14440         "::0",
14441         "::0"
14442 };
14443
14444 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14445         "1.2.3.1",
14446         "1.2.3.2",
14447         "1.2.3.3",
14448         "1.2.3.4",
14449         "1.2.3.5",
14450         "1.2.3.6",
14451         "1.2.3.7",
14452         "1.2.3.8",
14453         "1.2.3.9",
14454         "1.2.3.10",
14455         "1.2.3.11",
14456         "1.2.3.12",
14457         "1.2.3.13",
14458         "1001:1111:1111:1000:0:1111:1111:1111"
14459 };
14460
14461 static bool run_local_remove_duplicate_addrs2(int dummy)
14462 {
14463         struct samba_sockaddr test_vector[28];
14464         size_t count, i;
14465
14466         /* Construct the sockaddr_storage test vector. */
14467         for (i = 0; i < 28; i++) {
14468                 struct addrinfo hints;
14469                 struct addrinfo *res = NULL;
14470                 int ret;
14471
14472                 memset(&hints, '\0', sizeof(hints));
14473                 hints.ai_flags = AI_NUMERICHOST;
14474                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14475                                 NULL,
14476                                 &hints,
14477                                 &res);
14478                 if (ret) {
14479                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14480                                 remove_duplicate_addrs2_test_strings_vector[i]);
14481                         return false;
14482                 }
14483                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14484                 memcpy(&test_vector[i].u.ss,
14485                         res->ai_addr,
14486                         res->ai_addrlen);
14487                 freeaddrinfo(res);
14488         }
14489
14490         count = remove_duplicate_addrs2(test_vector, i);
14491
14492         if (count != 14) {
14493                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14494                         count);
14495                 return false;
14496         }
14497
14498         for (i = 0; i < count; i++) {
14499                 char addr[INET6_ADDRSTRLEN];
14500
14501                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14502
14503                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14504                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14505                                 i,
14506                                 addr,
14507                                 remove_duplicate_addrs2_test_strings_result[i]);
14508                         return false;
14509                 }
14510         }
14511
14512         printf("run_local_remove_duplicate_addrs2: success\n");
14513         return true;
14514 }
14515
14516 static bool run_local_tdb_opener(int dummy)
14517 {
14518         TDB_CONTEXT *t;
14519         unsigned v = 0;
14520
14521         while (1) {
14522                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14523                              O_RDWR|O_CREAT, 0755);
14524                 if (t == NULL) {
14525                         perror("tdb_open failed");
14526                         return false;
14527                 }
14528                 tdb_close(t);
14529
14530                 v += 1;
14531                 printf("\r%u", v);
14532         }
14533         return true;
14534 }
14535
14536 static bool run_local_tdb_writer(int dummy)
14537 {
14538         TDB_CONTEXT *t;
14539         unsigned v = 0;
14540         TDB_DATA val;
14541
14542         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14543         if (t == 0) {
14544                 perror("tdb_open failed");
14545                 return 1;
14546         }
14547
14548         val.dptr = (uint8_t *)&v;
14549         val.dsize = sizeof(v);
14550
14551         while (1) {
14552                 TDB_DATA data;
14553                 int ret;
14554
14555                 ret = tdb_store(t, val, val, 0);
14556                 if (ret != 0) {
14557                         printf("%s\n", tdb_errorstr(t));
14558                 }
14559                 v += 1;
14560                 printf("\r%u", v);
14561
14562                 data = tdb_fetch(t, val);
14563                 if (data.dptr != NULL) {
14564                         SAFE_FREE(data.dptr);
14565                 }
14566         }
14567         return true;
14568 }
14569
14570 static bool run_local_canonicalize_path(int dummy)
14571 {
14572         const char *src[] = {
14573                         "/foo/..",
14574                         "/..",
14575                         "/foo/bar/../baz",
14576                         "/foo/././",
14577                         "/../foo",
14578                         ".././././",
14579                         ".././././../../../boo",
14580                         "./..",
14581                         "/",
14582                         "/../../",
14583                         "/foo/../",
14584                         "/./././",
14585                         "/./././.",
14586                         "/.../././.",
14587                         "/./././.foo",
14588                         "/./././.foo.",
14589                         "/./././foo.",
14590                         "/foo/bar/..",
14591                         "/foo/bar/../baz/",
14592                         "////////////////",
14593                         "/////////./././././.",
14594                         "/./.././../.boo/../baz",
14595                         "/a/component/path",
14596                         "/a/component/path/",
14597                         "/a/component/path/..",
14598                         "/a/component/../path/",
14599                         "///a/./././///component/../////path/",
14600                         NULL
14601                         };
14602         const char *dst[] = {
14603                         "/",
14604                         "/",
14605                         "/foo/baz",
14606                         "/foo",
14607                         "/foo",
14608                         "/",
14609                         "/boo",
14610                         "/",
14611                         "/",
14612                         "/",
14613                         "/",
14614                         "/",
14615                         "/",
14616                         "/...",
14617                         "/.foo",
14618                         "/.foo.",
14619                         "/foo.",
14620                         "/foo",
14621                         "/foo/baz",
14622                         "/",
14623                         "/",
14624                         "/baz",
14625                         "/a/component/path",
14626                         "/a/component/path",
14627                         "/a/component",
14628                         "/a/path",
14629                         "/a/path",
14630                         NULL
14631                         };
14632         unsigned int i;
14633
14634         for (i = 0; src[i] != NULL; i++) {
14635                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14636                 if (d == NULL) {
14637                         perror("talloc fail\n");
14638                         return false;
14639                 }
14640                 if (strcmp(d, dst[i]) != 0) {
14641                         d_fprintf(stderr,
14642                                 "canonicalize mismatch %s -> %s != %s",
14643                                 src[i], d, dst[i]);
14644                         return false;
14645                 }
14646                 talloc_free(d);
14647         }
14648         return true;
14649 }
14650
14651 static bool run_ign_bad_negprot(int dummy)
14652 {
14653         struct tevent_context *ev;
14654         struct tevent_req *req;
14655         struct smbXcli_conn *conn;
14656         struct sockaddr_storage ss;
14657         NTSTATUS status;
14658         int fd;
14659         bool ok;
14660
14661         printf("starting ignore bad negprot\n");
14662
14663         ok = resolve_name(host, &ss, 0x20, true);
14664         if (!ok) {
14665                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14666                 return false;
14667         }
14668
14669         status = open_socket_out(&ss, 445, 10000, &fd);
14670         if (!NT_STATUS_IS_OK(status)) {
14671                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14672                           nt_errstr(status));
14673                 return false;
14674         }
14675
14676         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14677                                    NULL, 0, NULL);
14678         if (conn == NULL) {
14679                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14680                 return false;
14681         }
14682
14683         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14684         if (NT_STATUS_IS_OK(status)) {
14685                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14686                 return false;
14687         }
14688
14689         ev = samba_tevent_context_init(talloc_tos());
14690         if (ev == NULL) {
14691                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14692                 return false;
14693         }
14694
14695         req = smb1cli_session_setup_nt1_send(
14696                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14697                 data_blob_null, data_blob_null, 0x40,
14698                 "Windows 2000 2195", "Windows 2000 5.0");
14699         if (req == NULL) {
14700                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14701                 return false;
14702         }
14703
14704         ok = tevent_req_poll_ntstatus(req, ev, &status);
14705         if (!ok) {
14706                 d_fprintf(stderr, "tevent_req_poll failed\n");
14707                 return false;
14708         }
14709
14710         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14711                                                 NULL, NULL);
14712         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14713                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14714                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
14715                           nt_errstr(status));
14716                 return false;
14717         }
14718
14719         TALLOC_FREE(conn);
14720
14721         printf("starting ignore bad negprot\n");
14722
14723         return true;
14724 }
14725
14726 static double create_procs(bool (*fn)(int), bool *result)
14727 {
14728         int i, status;
14729         volatile pid_t *child_status;
14730         volatile bool *child_status_out;
14731         int synccount;
14732         int tries = 8;
14733         struct timeval start;
14734
14735         synccount = 0;
14736
14737         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14738         if (!child_status) {
14739                 printf("Failed to setup shared memory\n");
14740                 return -1;
14741         }
14742
14743         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14744         if (!child_status_out) {
14745                 printf("Failed to setup result status shared memory\n");
14746                 return -1;
14747         }
14748
14749         for (i = 0; i < torture_nprocs; i++) {
14750                 child_status[i] = 0;
14751                 child_status_out[i] = True;
14752         }
14753
14754         start = timeval_current();
14755
14756         for (i=0;i<torture_nprocs;i++) {
14757                 procnum = i;
14758                 if (fork() == 0) {
14759                         pid_t mypid = getpid();
14760                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14761
14762                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
14763
14764                         while (1) {
14765                                 if (torture_open_connection(&current_cli, i)) break;
14766                                 if (tries-- == 0) {
14767                                         printf("pid %d failed to start\n", (int)getpid());
14768                                         _exit(1);
14769                                 }
14770                                 smb_msleep(10); 
14771                         }
14772
14773                         child_status[i] = getpid();
14774
14775                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14776
14777                         child_status_out[i] = fn(i);
14778                         _exit(0);
14779                 }
14780         }
14781
14782         do {
14783                 synccount = 0;
14784                 for (i=0;i<torture_nprocs;i++) {
14785                         if (child_status[i]) synccount++;
14786                 }
14787                 if (synccount == torture_nprocs) break;
14788                 smb_msleep(10);
14789         } while (timeval_elapsed(&start) < 30);
14790
14791         if (synccount != torture_nprocs) {
14792                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14793                 *result = False;
14794                 return timeval_elapsed(&start);
14795         }
14796
14797         /* start the client load */
14798         start = timeval_current();
14799
14800         for (i=0;i<torture_nprocs;i++) {
14801                 child_status[i] = 0;
14802         }
14803
14804         printf("%d clients started\n", torture_nprocs);
14805
14806         for (i=0;i<torture_nprocs;i++) {
14807                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14808         }
14809
14810         printf("\n");
14811
14812         for (i=0;i<torture_nprocs;i++) {
14813                 if (!child_status_out[i]) {
14814                         *result = False;
14815                 }
14816         }
14817         return timeval_elapsed(&start);
14818 }
14819
14820 #define FLAG_MULTIPROC 1
14821
14822 static struct {
14823         const char *name;
14824         bool (*fn)(int);
14825         unsigned flags;
14826 } torture_ops[] = {
14827         {
14828                 .name = "FDPASS",
14829                 .fn   = run_fdpasstest,
14830         },
14831         {
14832                 .name = "LOCK1",
14833                 .fn   = run_locktest1,
14834         },
14835         {
14836                 .name = "LOCK2",
14837                 .fn   =  run_locktest2,
14838         },
14839         {
14840                 .name = "LOCK3",
14841                 .fn   =  run_locktest3,
14842         },
14843         {
14844                 .name = "LOCK4",
14845                 .fn   =  run_locktest4,
14846         },
14847         {
14848                 .name = "LOCK5",
14849                 .fn   =  run_locktest5,
14850         },
14851         {
14852                 .name = "LOCK6",
14853                 .fn   =  run_locktest6,
14854         },
14855         {
14856                 .name = "LOCK7",
14857                 .fn   =  run_locktest7,
14858         },
14859         {
14860                 .name = "LOCK8",
14861                 .fn   =  run_locktest8,
14862         },
14863         {
14864                 .name = "LOCK9A",
14865                 .fn   =  run_locktest9a,
14866         },
14867         {
14868                 .name = "LOCK9B",
14869                 .fn   =  run_locktest9b,
14870         },
14871         {
14872                 .name = "LOCK10",
14873                 .fn   =  run_locktest10,
14874         },
14875         {
14876                 .name = "LOCK11",
14877                 .fn   =  run_locktest11,
14878         },
14879         {
14880                 .name = "LOCK12",
14881                 .fn   =  run_locktest12,
14882         },
14883         {
14884                 .name = "LOCK13",
14885                 .fn   =  run_locktest13,
14886         },
14887         {
14888                 .name = "UNLINK",
14889                 .fn   = run_unlinktest,
14890         },
14891         {
14892                 .name = "BROWSE",
14893                 .fn   = run_browsetest,
14894         },
14895         {
14896                 .name = "ATTR",
14897                 .fn   =   run_attrtest,
14898         },
14899         {
14900                 .name = "TRANS2",
14901                 .fn   = run_trans2test,
14902         },
14903         {
14904                 .name  = "MAXFID",
14905                 .fn    = run_maxfidtest,
14906                 .flags = FLAG_MULTIPROC,
14907         },
14908         {
14909                 .name  = "TORTURE",
14910                 .fn    = run_torture,
14911                 .flags = FLAG_MULTIPROC,
14912         },
14913         {
14914                 .name  = "RANDOMIPC",
14915                 .fn    = run_randomipc,
14916         },
14917         {
14918                 .name  = "NEGNOWAIT",
14919                 .fn    = run_negprot_nowait,
14920         },
14921         {
14922                 .name  = "NBENCH",
14923                 .fn    =  run_nbench,
14924         },
14925         {
14926                 .name  = "NBENCH2",
14927                 .fn    = run_nbench2,
14928         },
14929         {
14930                 .name  = "OPLOCK1",
14931                 .fn    =  run_oplock1,
14932         },
14933         {
14934                 .name  = "OPLOCK2",
14935                 .fn    =  run_oplock2,
14936         },
14937         {
14938                 .name  = "OPLOCK4",
14939                 .fn    =  run_oplock4,
14940         },
14941 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14942         {
14943                 .name  = "OPLOCK5",
14944                 .fn    =  run_oplock5,
14945         },
14946 #endif
14947         {
14948                 .name  = "DIR",
14949                 .fn    =  run_dirtest,
14950         },
14951         {
14952                 .name  = "DIR1",
14953                 .fn    =  run_dirtest1,
14954         },
14955         {
14956                 .name  = "DIR-CREATETIME",
14957                 .fn    =  run_dir_createtime,
14958         },
14959         {
14960                 .name  = "DENY1",
14961                 .fn    =  torture_denytest1,
14962         },
14963         {
14964                 .name  = "DENY2",
14965                 .fn    =  torture_denytest2,
14966         },
14967         {
14968                 .name  = "TCON",
14969                 .fn    =  run_tcon_test,
14970         },
14971         {
14972                 .name  = "TCONDEV",
14973                 .fn    =  run_tcon_devtype_test,
14974         },
14975         {
14976                 .name  = "RW1",
14977                 .fn    =  run_readwritetest,
14978         },
14979         {
14980                 .name  = "RW2",
14981                 .fn    =  run_readwritemulti,
14982                 .flags = FLAG_MULTIPROC
14983         },
14984         {
14985                 .name  = "RW3",
14986                 .fn    =  run_readwritelarge,
14987         },
14988         {
14989                 .name  = "RW-SIGNING",
14990                 .fn    =  run_readwritelarge_signtest,
14991         },
14992         {
14993                 .name  = "OPEN",
14994                 .fn    = run_opentest,
14995         },
14996         {
14997                 .name  = "POSIX",
14998                 .fn    = run_simple_posix_open_test,
14999         },
15000         {
15001                 .name  = "POSIX-APPEND",
15002                 .fn    = run_posix_append,
15003         },
15004         {
15005                 .name  = "POSIX-SYMLINK-ACL",
15006                 .fn    = run_acl_symlink_test,
15007         },
15008         {
15009                 .name  = "POSIX-SYMLINK-EA",
15010                 .fn    = run_ea_symlink_test,
15011         },
15012         {
15013                 .name  = "POSIX-STREAM-DELETE",
15014                 .fn    = run_posix_stream_delete,
15015         },
15016         {
15017                 .name  = "POSIX-OFD-LOCK",
15018                 .fn    = run_posix_ofd_lock_test,
15019         },
15020         {
15021                 .name  = "POSIX-BLOCKING-LOCK",
15022                 .fn    = run_posix_blocking_lock,
15023         },
15024         {
15025                 .name  = "POSIX-MKDIR",
15026                 .fn    = run_posix_mkdir_test,
15027         },
15028         {
15029                 .name  = "POSIX-ACL-OPLOCK",
15030                 .fn    = run_posix_acl_oplock_test,
15031         },
15032         {
15033                 .name  = "POSIX-ACL-SHAREROOT",
15034                 .fn    = run_posix_acl_shareroot_test,
15035         },
15036         {
15037                 .name  = "POSIX-LS-WILDCARD",
15038                 .fn    = run_posix_ls_wildcard_test,
15039         },
15040         {
15041                 .name  = "POSIX-LS-SINGLE",
15042                 .fn    = run_posix_ls_single_test,
15043         },
15044         {
15045                 .name  = "POSIX-READLINK",
15046                 .fn    = run_posix_readlink_test,
15047         },
15048         {
15049                 .name  = "POSIX-STAT",
15050                 .fn    = run_posix_stat_test,
15051         },
15052         {
15053                 .name  = "POSIX-SYMLINK-PARENT",
15054                 .fn    = run_posix_symlink_parent_test,
15055         },
15056         {
15057                 .name  = "POSIX-SYMLINK-CHMOD",
15058                 .fn    = run_posix_symlink_chmod_test,
15059         },
15060         {
15061                 .name  = "POSIX-SYMLINK-RENAME",
15062                 .fn    = run_posix_symlink_rename_test,
15063         },
15064         {
15065                 .name  = "POSIX-DIR-DEFAULT-ACL",
15066                 .fn    = run_posix_dir_default_acl_test,
15067         },
15068         {
15069                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15070                 .fn    = run_posix_symlink_getpathinfo_test,
15071         },
15072         {
15073                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15074                 .fn    = run_posix_symlink_setpathinfo_test,
15075         },
15076         {
15077                 .name  = "WINDOWS-BAD-SYMLINK",
15078                 .fn    = run_symlink_open_test,
15079         },
15080         {
15081                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15082                 .fn    = run_smb1_wild_mangle_unlink_test,
15083         },
15084         {
15085                 .name  = "SMB1-WILD-MANGLE-RENAME",
15086                 .fn    = run_smb1_wild_mangle_rename_test,
15087         },
15088         {
15089                 .name  = "CASE-INSENSITIVE-CREATE",
15090                 .fn    = run_case_insensitive_create,
15091         },
15092         {
15093                 .name  = "ASYNC-ECHO",
15094                 .fn    = run_async_echo,
15095         },
15096         {
15097                 .name  = "UID-REGRESSION-TEST",
15098                 .fn    = run_uid_regression_test,
15099         },
15100         {
15101                 .name  = "SHORTNAME-TEST",
15102                 .fn    = run_shortname_test,
15103         },
15104         {
15105                 .name  = "ADDRCHANGE",
15106                 .fn    = run_addrchange,
15107         },
15108 #if 1
15109         {
15110                 .name  = "OPENATTR",
15111                 .fn    = run_openattrtest,
15112         },
15113 #endif
15114         {
15115                 .name  = "XCOPY",
15116                 .fn    = run_xcopy,
15117         },
15118         {
15119                 .name  = "RENAME",
15120                 .fn    = run_rename,
15121         },
15122         {
15123                 .name  = "RENAME-ACCESS",
15124                 .fn    = run_rename_access,
15125         },
15126         {
15127                 .name  = "OWNER-RIGHTS",
15128                 .fn    = run_owner_rights,
15129         },
15130         {
15131                 .name  = "DELETE",
15132                 .fn    = run_deletetest,
15133         },
15134         {
15135                 .name  = "DELETE-STREAM",
15136                 .fn    = run_delete_stream,
15137         },
15138         {
15139                 .name  = "DELETE-PRINT",
15140                 .fn    = run_delete_print_test,
15141         },
15142         {
15143                 .name  = "DELETE-LN",
15144                 .fn    = run_deletetest_ln,
15145         },
15146         {
15147                 .name  = "PROPERTIES",
15148                 .fn    = run_properties,
15149         },
15150         {
15151                 .name  = "MANGLE",
15152                 .fn    = torture_mangle,
15153         },
15154         {
15155                 .name  = "MANGLE1",
15156                 .fn    = run_mangle1,
15157         },
15158         {
15159                 .name  = "MANGLE-ILLEGAL",
15160                 .fn    = run_mangle_illegal,
15161         },
15162         {
15163                 .name  = "W2K",
15164                 .fn    = run_w2ktest,
15165         },
15166         {
15167                 .name  = "TRANS2SCAN",
15168                 .fn    = torture_trans2_scan,
15169         },
15170         {
15171                 .name  = "NTTRANSSCAN",
15172                 .fn    = torture_nttrans_scan,
15173         },
15174         {
15175                 .name  = "UTABLE",
15176                 .fn    = torture_utable,
15177         },
15178         {
15179                 .name  = "CASETABLE",
15180                 .fn    = torture_casetable,
15181         },
15182         {
15183                 .name  = "ERRMAPEXTRACT",
15184                 .fn    = run_error_map_extract,
15185         },
15186         {
15187                 .name  = "PIPE_NUMBER",
15188                 .fn    = run_pipe_number,
15189         },
15190         {
15191                 .name  = "TCON2",
15192                 .fn    =  run_tcon2_test,
15193         },
15194         {
15195                 .name  = "IOCTL",
15196                 .fn    =  torture_ioctl_test,
15197         },
15198         {
15199                 .name  = "CHKPATH",
15200                 .fn    =  torture_chkpath_test,
15201         },
15202         {
15203                 .name  = "FDSESS",
15204                 .fn    = run_fdsesstest,
15205         },
15206         {
15207                 .name  = "EATEST",
15208                 .fn    = run_eatest,
15209         },
15210         {
15211                 .name  = "SESSSETUP_BENCH",
15212                 .fn    = run_sesssetup_bench,
15213         },
15214         {
15215                 .name  = "CHAIN1",
15216                 .fn    = run_chain1,
15217         },
15218         {
15219                 .name  = "CHAIN2",
15220                 .fn    = run_chain2,
15221         },
15222         {
15223                 .name  = "CHAIN3",
15224                 .fn    = run_chain3,
15225         },
15226         {
15227                 .name  = "WINDOWS-WRITE",
15228                 .fn    = run_windows_write,
15229         },
15230         {
15231                 .name  = "LARGE_READX",
15232                 .fn    = run_large_readx,
15233         },
15234         {
15235                 .name  = "MSDFS-ATTRIBUTE",
15236                 .fn    = run_msdfs_attribute,
15237         },
15238         {
15239                 .name  = "NTTRANS-CREATE",
15240                 .fn    = run_nttrans_create,
15241         },
15242         {
15243                 .name  = "NTTRANS-FSCTL",
15244                 .fn    = run_nttrans_fsctl,
15245         },
15246         {
15247                 .name  = "CLI_ECHO",
15248                 .fn    = run_cli_echo,
15249         },
15250         {
15251                 .name  = "CLI_SPLICE",
15252                 .fn    = run_cli_splice,
15253         },
15254         {
15255                 .name  = "TLDAP",
15256                 .fn    = run_tldap,
15257         },
15258         {
15259                 .name  = "STREAMERROR",
15260                 .fn    = run_streamerror,
15261         },
15262         {
15263                 .name  = "NOTIFY-BENCH",
15264                 .fn    = run_notify_bench,
15265         },
15266         {
15267                 .name  = "NOTIFY-BENCH2",
15268                 .fn    = run_notify_bench2,
15269         },
15270         {
15271                 .name  = "NOTIFY-BENCH3",
15272                 .fn    = run_notify_bench3,
15273         },
15274         {
15275                 .name  = "BAD-NBT-SESSION",
15276                 .fn    = run_bad_nbt_session,
15277         },
15278         {
15279                 .name  = "IGN-BAD-NEGPROT",
15280                 .fn    = run_ign_bad_negprot,
15281         },
15282         {
15283                 .name  = "SMB-ANY-CONNECT",
15284                 .fn    = run_smb_any_connect,
15285         },
15286         {
15287                 .name  = "NOTIFY-ONLINE",
15288                 .fn    = run_notify_online,
15289         },
15290         {
15291                 .name  = "SMB2-BASIC",
15292                 .fn    = run_smb2_basic,
15293         },
15294         {
15295                 .name  = "SMB2-NEGPROT",
15296                 .fn    = run_smb2_negprot,
15297         },
15298         {
15299                 .name  = "SMB2-ANONYMOUS",
15300                 .fn    = run_smb2_anonymous,
15301         },
15302         {
15303                 .name  = "SMB2-SESSION-RECONNECT",
15304                 .fn    = run_smb2_session_reconnect,
15305         },
15306         {
15307                 .name  = "SMB2-TCON-DEPENDENCE",
15308                 .fn    = run_smb2_tcon_dependence,
15309         },
15310         {
15311                 .name  = "SMB2-MULTI-CHANNEL",
15312                 .fn    = run_smb2_multi_channel,
15313         },
15314         {
15315                 .name  = "SMB2-SESSION-REAUTH",
15316                 .fn    = run_smb2_session_reauth,
15317         },
15318         {
15319                 .name  = "SMB2-FTRUNCATE",
15320                 .fn    = run_smb2_ftruncate,
15321         },
15322         {
15323                 .name  = "SMB2-DIR-FSYNC",
15324                 .fn    = run_smb2_dir_fsync,
15325         },
15326         {
15327                 .name  = "SMB2-PATH-SLASH",
15328                 .fn    = run_smb2_path_slash,
15329         },
15330         {
15331                 .name  = "SMB1-SYSTEM-SECURITY",
15332                 .fn    = run_smb1_system_security,
15333         },
15334         {
15335                 .name  = "SMB2-SACL",
15336                 .fn    = run_smb2_sacl,
15337         },
15338         {
15339                 .name  = "SMB2-QUOTA1",
15340                 .fn    = run_smb2_quota1,
15341         },
15342         {
15343                 .name  = "SMB2-STREAM-ACL",
15344                 .fn    = run_smb2_stream_acl,
15345         },
15346         {
15347                 .name  = "SMB2-LIST-DIR-ASYNC",
15348                 .fn    = run_list_dir_async_test,
15349         },
15350         {
15351                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15352                 .fn    = run_delete_on_close_non_empty,
15353         },
15354         {
15355                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15356                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15357         },
15358         {
15359                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15360                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15361         },
15362         {
15363                 .name  = "SMB2-DFS-PATHS",
15364                 .fn    = run_smb2_dfs_paths,
15365         },
15366         {
15367                 .name  = "SMB1-DFS-PATHS",
15368                 .fn    = run_smb1_dfs_paths,
15369         },
15370         {
15371                 .name  = "SMB1-DFS-SEARCH-PATHS",
15372                 .fn    = run_smb1_dfs_search_paths,
15373         },
15374         {
15375                 .name  = "CLEANUP1",
15376                 .fn    = run_cleanup1,
15377         },
15378         {
15379                 .name  = "CLEANUP2",
15380                 .fn    = run_cleanup2,
15381         },
15382         {
15383                 .name  = "CLEANUP4",
15384                 .fn    = run_cleanup4,
15385         },
15386         {
15387                 .name  = "OPLOCK-CANCEL",
15388                 .fn    = run_oplock_cancel,
15389         },
15390         {
15391                 .name  = "PIDHIGH",
15392                 .fn    = run_pidhigh,
15393         },
15394         {
15395                 .name  = "LOCAL-SUBSTITUTE",
15396                 .fn    = run_local_substitute,
15397         },
15398         {
15399                 .name  = "LOCAL-GENCACHE",
15400                 .fn    = run_local_gencache,
15401         },
15402         {
15403                 .name  = "LOCAL-DBWRAP-WATCH1",
15404                 .fn    = run_dbwrap_watch1,
15405         },
15406         {
15407                 .name  = "LOCAL-DBWRAP-WATCH2",
15408                 .fn    = run_dbwrap_watch2,
15409         },
15410         {
15411                 .name  = "LOCAL-DBWRAP-WATCH3",
15412                 .fn    = run_dbwrap_watch3,
15413         },
15414         {
15415                 .name  = "LOCAL-DBWRAP-WATCH4",
15416                 .fn    = run_dbwrap_watch4,
15417         },
15418         {
15419                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
15420                 .fn    = run_dbwrap_do_locked1,
15421         },
15422         {
15423                 .name  = "LOCAL-MESSAGING-READ1",
15424                 .fn    = run_messaging_read1,
15425         },
15426         {
15427                 .name  = "LOCAL-MESSAGING-READ2",
15428                 .fn    = run_messaging_read2,
15429         },
15430         {
15431                 .name  = "LOCAL-MESSAGING-READ3",
15432                 .fn    = run_messaging_read3,
15433         },
15434         {
15435                 .name  = "LOCAL-MESSAGING-READ4",
15436                 .fn    = run_messaging_read4,
15437         },
15438         {
15439                 .name  = "LOCAL-MESSAGING-FDPASS1",
15440                 .fn    = run_messaging_fdpass1,
15441         },
15442         {
15443                 .name  = "LOCAL-MESSAGING-FDPASS2",
15444                 .fn    = run_messaging_fdpass2,
15445         },
15446         {
15447                 .name  = "LOCAL-MESSAGING-FDPASS2a",
15448                 .fn    = run_messaging_fdpass2a,
15449         },
15450         {
15451                 .name  = "LOCAL-MESSAGING-FDPASS2b",
15452                 .fn    = run_messaging_fdpass2b,
15453         },
15454         {
15455                 .name  = "LOCAL-MESSAGING-SEND-ALL",
15456                 .fn    = run_messaging_send_all,
15457         },
15458         {
15459                 .name  = "LOCAL-BASE64",
15460                 .fn    = run_local_base64,
15461         },
15462         {
15463                 .name  = "LOCAL-RBTREE",
15464                 .fn    = run_local_rbtree,
15465         },
15466         {
15467                 .name  = "LOCAL-MEMCACHE",
15468                 .fn    = run_local_memcache,
15469         },
15470         {
15471                 .name  = "LOCAL-STREAM-NAME",
15472                 .fn    = run_local_stream_name,
15473         },
15474         {
15475                 .name  = "LOCAL-STR-MATCH-MSWILD",
15476                 .fn    = run_str_match_mswild,
15477         },
15478         {
15479                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
15480                 .fn    = run_str_match_regex_sub1,
15481         },
15482         {
15483                 .name  = "WBCLIENT-MULTI-PING",
15484                 .fn    = run_wbclient_multi_ping,
15485         },
15486         {
15487                 .name  = "LOCAL-string_to_sid",
15488                 .fn    = run_local_string_to_sid,
15489         },
15490         {
15491                 .name  = "LOCAL-sid_to_string",
15492                 .fn    = run_local_sid_to_string,
15493         },
15494         {
15495                 .name  = "LOCAL-binary_to_sid",
15496                 .fn    = run_local_binary_to_sid,
15497         },
15498         {
15499                 .name  = "LOCAL-DBTRANS",
15500                 .fn    = run_local_dbtrans,
15501         },
15502         {
15503                 .name  = "LOCAL-TEVENT-POLL",
15504                 .fn    = run_local_tevent_poll,
15505         },
15506         {
15507                 .name  = "LOCAL-CONVERT-STRING",
15508                 .fn    = run_local_convert_string,
15509         },
15510         {
15511                 .name  = "LOCAL-CONV-AUTH-INFO",
15512                 .fn    = run_local_conv_auth_info,
15513         },
15514         {
15515                 .name  = "LOCAL-hex_encode_buf",
15516                 .fn    = run_local_hex_encode_buf,
15517         },
15518         {
15519                 .name  = "LOCAL-IDMAP-TDB-COMMON",
15520                 .fn    = run_idmap_tdb_common_test,
15521         },
15522         {
15523                 .name  = "LOCAL-remove_duplicate_addrs2",
15524                 .fn    = run_local_remove_duplicate_addrs2,
15525         },
15526         {
15527                 .name  = "local-tdb-opener",
15528                 .fn    = run_local_tdb_opener,
15529         },
15530         {
15531                 .name  = "local-tdb-writer",
15532                 .fn    = run_local_tdb_writer,
15533         },
15534         {
15535                 .name  = "LOCAL-DBWRAP-CTDB1",
15536                 .fn    = run_local_dbwrap_ctdb1,
15537         },
15538         {
15539                 .name  = "LOCAL-BENCH-PTHREADPOOL",
15540                 .fn    = run_bench_pthreadpool,
15541         },
15542         {
15543                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
15544                 .fn    = run_pthreadpool_tevent,
15545         },
15546         {
15547                 .name  = "LOCAL-G-LOCK1",
15548                 .fn    = run_g_lock1,
15549         },
15550         {
15551                 .name  = "LOCAL-G-LOCK2",
15552                 .fn    = run_g_lock2,
15553         },
15554         {
15555                 .name  = "LOCAL-G-LOCK3",
15556                 .fn    = run_g_lock3,
15557         },
15558         {
15559                 .name  = "LOCAL-G-LOCK4",
15560                 .fn    = run_g_lock4,
15561         },
15562         {
15563                 .name  = "LOCAL-G-LOCK4A",
15564                 .fn    = run_g_lock4a,
15565         },
15566         {
15567                 .name  = "LOCAL-G-LOCK5",
15568                 .fn    = run_g_lock5,
15569         },
15570         {
15571                 .name  = "LOCAL-G-LOCK6",
15572                 .fn    = run_g_lock6,
15573         },
15574         {
15575                 .name  = "LOCAL-G-LOCK7",
15576                 .fn    = run_g_lock7,
15577         },
15578         {
15579                 .name  = "LOCAL-G-LOCK8",
15580                 .fn    = run_g_lock8,
15581         },
15582         {
15583                 .name  = "LOCAL-G-LOCK-PING-PONG",
15584                 .fn    = run_g_lock_ping_pong,
15585         },
15586         {
15587                 .name  = "LOCAL-CANONICALIZE-PATH",
15588                 .fn    = run_local_canonicalize_path,
15589         },
15590         {
15591                 .name  = "LOCAL-NAMEMAP-CACHE1",
15592                 .fn    = run_local_namemap_cache1,
15593         },
15594         {
15595                 .name  = "LOCAL-IDMAP-CACHE1",
15596                 .fn    = run_local_idmap_cache1,
15597         },
15598         {
15599                 .name  = "qpathinfo-bufsize",
15600                 .fn    = run_qpathinfo_bufsize,
15601         },
15602         {
15603                 .name  = "hide-new-files-timeout",
15604                 .fn    = run_hidenewfiles,
15605         },
15606 #ifdef CLUSTER_SUPPORT
15607         {
15608                 .name  = "ctdbd-conn1",
15609                 .fn    = run_ctdbd_conn1,
15610         },
15611 #endif
15612         {
15613                 .name  = "readdir-timestamp",
15614                 .fn    = run_readdir_timestamp,
15615         },
15616         {
15617                 .name = NULL,
15618         },
15619 };
15620
15621 /****************************************************************************
15622 run a specified test or "ALL"
15623 ****************************************************************************/
15624 static bool run_test(const char *name)
15625 {
15626         bool ret = True;
15627         bool result = True;
15628         bool found = False;
15629         int i;
15630         double t;
15631         if (strequal(name,"ALL")) {
15632                 for (i=0;torture_ops[i].name;i++) {
15633                         run_test(torture_ops[i].name);
15634                 }
15635                 found = True;
15636         }
15637
15638         for (i=0;torture_ops[i].name;i++) {
15639                 fstr_sprintf(randomfname, "\\XX%x", 
15640                          (unsigned)random());
15641
15642                 if (strequal(name, torture_ops[i].name)) {
15643                         found = True;
15644                         printf("Running %s\n", name);
15645                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
15646                                 t = create_procs(torture_ops[i].fn, &result);
15647                                 if (!result) { 
15648                                         ret = False;
15649                                         printf("TEST %s FAILED!\n", name);
15650                                 }
15651                         } else {
15652                                 struct timeval start;
15653                                 start = timeval_current();
15654                                 if (!torture_ops[i].fn(0)) {
15655                                         ret = False;
15656                                         printf("TEST %s FAILED!\n", name);
15657                                 }
15658                                 t = timeval_elapsed(&start);
15659                         }
15660                         printf("%s took %g secs\n\n", name, t);
15661                 }
15662         }
15663
15664         if (!found) {
15665                 printf("Did not find a test named %s\n", name);
15666                 ret = False;
15667         }
15668
15669         return ret;
15670 }
15671
15672
15673 static void usage(void)
15674 {
15675         int i;
15676
15677         printf("WARNING samba4 test suite is much more complete nowadays.\n");
15678         printf("Please use samba4 torture.\n\n");
15679
15680         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15681
15682         printf("\t-d debuglevel\n");
15683         printf("\t-U user%%pass\n");
15684         printf("\t-k                    use kerberos\n");
15685         printf("\t-N numprocs\n");
15686         printf("\t-n my_netbios_name\n");
15687         printf("\t-W workgroup\n");
15688         printf("\t-o num_operations\n");
15689         printf("\t-O socket_options\n");
15690         printf("\t-m maximum protocol\n");
15691         printf("\t-L use oplocks\n");
15692         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
15693         printf("\t-A showall\n");
15694         printf("\t-p port\n");
15695         printf("\t-s seed\n");
15696         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
15697         printf("\t-f filename           filename to test\n");
15698         printf("\t-e                    encrypt\n");
15699         printf("\n\n");
15700
15701         printf("tests are:");
15702         for (i=0;torture_ops[i].name;i++) {
15703                 printf(" %s", torture_ops[i].name);
15704         }
15705         printf("\n");
15706
15707         printf("default test is ALL\n");
15708
15709         exit(1);
15710 }
15711
15712 /****************************************************************************
15713   main program
15714 ****************************************************************************/
15715  int main(int argc,char *argv[])
15716 {
15717         int opt, i;
15718         char *p;
15719         int gotuser = 0;
15720         int gotpass = 0;
15721         bool correct = True;
15722         TALLOC_CTX *frame = talloc_stackframe();
15723         int seed = time(NULL);
15724
15725 #ifdef HAVE_SETBUFFER
15726         setbuffer(stdout, NULL, 0);
15727 #endif
15728
15729         setup_logging("smbtorture", DEBUG_STDOUT);
15730
15731         smb_init_locale();
15732         fault_setup();
15733
15734         if (is_default_dyn_CONFIGFILE()) {
15735                 if(getenv("SMB_CONF_PATH")) {
15736                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15737                 }
15738         }
15739         lp_load_global(get_dyn_CONFIGFILE());
15740         load_interfaces();
15741
15742         if (argc < 2) {
15743                 usage();
15744         }
15745
15746         for(p = argv[1]; *p; p++)
15747           if(*p == '\\')
15748             *p = '/';
15749
15750         if (strncmp(argv[1], "//", 2)) {
15751                 usage();
15752         }
15753
15754         fstrcpy(host, &argv[1][2]);
15755         p = strchr_m(&host[2],'/');
15756         if (!p) {
15757                 usage();
15758         }
15759         *p = 0;
15760         fstrcpy(share, p+1);
15761
15762         fstrcpy(myname, get_myname(talloc_tos()));
15763         if (!*myname) {
15764                 fprintf(stderr, "Failed to get my hostname.\n");
15765                 return 1;
15766         }
15767
15768         if (*username == 0 && getenv("LOGNAME")) {
15769           fstrcpy(username,getenv("LOGNAME"));
15770         }
15771
15772         argc--;
15773         argv++;
15774
15775         fstrcpy(workgroup, lp_workgroup());
15776
15777         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15778                != EOF) {
15779                 switch (opt) {
15780                 case 'p':
15781                         port_to_use = atoi(optarg);
15782                         break;
15783                 case 's':
15784                         seed = atoi(optarg);
15785                         break;
15786                 case 'W':
15787                         fstrcpy(workgroup,optarg);
15788                         break;
15789                 case 'm':
15790                         lp_set_cmdline("client max protocol", optarg);
15791                         break;
15792                 case 'N':
15793                         torture_nprocs = atoi(optarg);
15794                         break;
15795                 case 'o':
15796                         torture_numops = atoi(optarg);
15797                         break;
15798                 case 'd':
15799                         lp_set_cmdline("log level", optarg);
15800                         break;
15801                 case 'O':
15802                         sockops = optarg;
15803                         break;
15804                 case 'L':
15805                         use_oplocks = True;
15806                         break;
15807                 case 'l':
15808                         local_path = optarg;
15809                         break;
15810                 case 'A':
15811                         torture_showall = True;
15812                         break;
15813                 case 'n':
15814                         fstrcpy(myname, optarg);
15815                         break;
15816                 case 'c':
15817                         client_txt = optarg;
15818                         break;
15819                 case 'e':
15820                         do_encrypt = true;
15821                         break;
15822                 case 'k':
15823 #ifdef HAVE_KRB5
15824                         use_kerberos = True;
15825 #else
15826                         d_printf("No kerberos support compiled in\n");
15827                         exit(1);
15828 #endif
15829                         break;
15830                 case 'U':
15831                         gotuser = 1;
15832                         fstrcpy(username,optarg);
15833                         p = strchr_m(username,'%');
15834                         if (p) {
15835                                 *p = 0;
15836                                 fstrcpy(password, p+1);
15837                                 gotpass = 1;
15838                         }
15839                         break;
15840                 case 'b':
15841                         fstrcpy(multishare_conn_fname, optarg);
15842                         use_multishare_conn = True;
15843                         break;
15844                 case 'B':
15845                         torture_blocksize = atoi(optarg);
15846                         break;
15847                 case 'f':
15848                         test_filename = SMB_STRDUP(optarg);
15849                         break;
15850                 default:
15851                         printf("Unknown option %c (%d)\n", (char)opt, opt);
15852                         usage();
15853                 }
15854         }
15855
15856         d_printf("using seed %d\n", seed);
15857
15858         srandom(seed);
15859
15860         if(use_kerberos && !gotuser) gotpass = True;
15861
15862         while (!gotpass) {
15863                 char pwd[256] = {0};
15864                 int rc;
15865
15866                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15867                 if (rc == 0) {
15868                         fstrcpy(password, pwd);
15869                         gotpass = 1;
15870                 }
15871         }
15872
15873         printf("host=%s share=%s user=%s myname=%s\n", 
15874                host, share, username, myname);
15875
15876         torture_creds = cli_session_creds_init(frame,
15877                                                username,
15878                                                workgroup,
15879                                                NULL, /* realm */
15880                                                password,
15881                                                use_kerberos,
15882                                                false, /* fallback_after_kerberos */
15883                                                false, /* use_ccache */
15884                                                false); /* password_is_nt_hash */
15885         if (torture_creds == NULL) {
15886                 d_printf("cli_session_creds_init() failed.\n");
15887                 exit(1);
15888         }
15889
15890         if (argc == optind) {
15891                 correct = run_test("ALL");
15892         } else {
15893                 for (i=optind;i<argc;i++) {
15894                         if (!run_test(argv[i])) {
15895                                 correct = False;
15896                         }
15897                 }
15898         }
15899
15900         TALLOC_FREE(frame);
15901
15902         if (correct) {
15903                 return(0);
15904         } else {
15905                 return(1);
15906         }
15907 }