86a6e928e14c4b93449e6ef3c598cb62c951234c
[metze/samba-autobuild/.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 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
660                         const char *fname,
661                         time_t *change_time,
662                         time_t *access_time,
663                         time_t *write_time,
664                         off_t *size,
665                         uint32_t *pattr)
666 {
667         int timezone = smb1cli_conn_server_time_zone(cli->conn);
668         time_t (*date_fn)(const void *buf, int serverzone) = NULL;
669         uint8_t *rdata = NULL;
670         uint32_t num_rdata;
671         NTSTATUS status;
672
673         status = cli_qpathinfo(talloc_tos(),
674                                cli,
675                                fname,
676                                SMB_INFO_STANDARD,
677                                22,
678                                CLI_BUFFER_SIZE,
679                                &rdata,
680                                &num_rdata);
681         if (!NT_STATUS_IS_OK(status)) {
682                 return status;
683         }
684         if (cli->win95) {
685                 date_fn = make_unix_date;
686         } else {
687                 date_fn = make_unix_date2;
688         }
689
690         if (change_time) {
691                 *change_time = date_fn(rdata + 0, timezone);
692         }
693         if (access_time) {
694                 *access_time = date_fn(rdata + 4, timezone);
695         }
696         if (write_time) {
697                 *write_time = date_fn(rdata + 8, timezone);
698         }
699         if (size) {
700                 *size = PULL_LE_U32(rdata, 12);
701         }
702         if (pattr) {
703                 *pattr = PULL_LE_U16(rdata, l1_attrFile);
704         }
705         return NT_STATUS_OK;
706 }
707
708 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
709 {
710         NTSTATUS status;
711
712         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
713
714         while (!NT_STATUS_IS_OK(status)) {
715                 if (!check_both_error(__LINE__, status, ERRDOS,
716                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
717                         return false;
718                 }
719
720                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
721         }
722
723         return true;
724 }
725
726
727 static bool rw_torture(struct cli_state *c)
728 {
729         const char *lockfname = "\\torture.lck";
730         fstring fname;
731         uint16_t fnum;
732         uint16_t fnum2;
733         pid_t pid2, pid = getpid();
734         int i, j;
735         char buf[1024];
736         bool correct = True;
737         size_t nread = 0;
738         NTSTATUS status;
739
740         memset(buf, '\0', sizeof(buf));
741
742         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
743                          DENY_NONE, &fnum2);
744         if (!NT_STATUS_IS_OK(status)) {
745                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
746         }
747         if (!NT_STATUS_IS_OK(status)) {
748                 printf("open of %s failed (%s)\n",
749                        lockfname, nt_errstr(status));
750                 return False;
751         }
752
753         for (i=0;i<torture_numops;i++) {
754                 unsigned n = (unsigned)sys_random()%10;
755
756                 if (i % 10 == 0) {
757                         printf("%d\r", i); fflush(stdout);
758                 }
759                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
760
761                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
762                         return False;
763                 }
764
765                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
766                                   DENY_ALL, &fnum);
767                 if (!NT_STATUS_IS_OK(status)) {
768                         printf("open failed (%s)\n", nt_errstr(status));
769                         correct = False;
770                         break;
771                 }
772
773                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
774                                       sizeof(pid), NULL);
775                 if (!NT_STATUS_IS_OK(status)) {
776                         printf("write failed (%s)\n", nt_errstr(status));
777                         correct = False;
778                 }
779
780                 for (j=0;j<50;j++) {
781                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
782                                               sizeof(pid)+(j*sizeof(buf)),
783                                               sizeof(buf), NULL);
784                         if (!NT_STATUS_IS_OK(status)) {
785                                 printf("write failed (%s)\n",
786                                        nt_errstr(status));
787                                 correct = False;
788                         }
789                 }
790
791                 pid2 = 0;
792
793                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
794                                   &nread);
795                 if (!NT_STATUS_IS_OK(status)) {
796                         printf("read failed (%s)\n", nt_errstr(status));
797                         correct = false;
798                 } else if (nread != sizeof(pid)) {
799                         printf("read/write compare failed: "
800                                "recv %ld req %ld\n", (unsigned long)nread,
801                                (unsigned long)sizeof(pid));
802                         correct = false;
803                 }
804
805                 if (pid2 != pid) {
806                         printf("data corruption!\n");
807                         correct = False;
808                 }
809
810                 status = cli_close(c, fnum);
811                 if (!NT_STATUS_IS_OK(status)) {
812                         printf("close failed (%s)\n", nt_errstr(status));
813                         correct = False;
814                 }
815
816                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
817                 if (!NT_STATUS_IS_OK(status)) {
818                         printf("unlink failed (%s)\n", nt_errstr(status));
819                         correct = False;
820                 }
821
822                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
823                 if (!NT_STATUS_IS_OK(status)) {
824                         printf("unlock failed (%s)\n", nt_errstr(status));
825                         correct = False;
826                 }
827         }
828
829         cli_close(c, fnum2);
830         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
831
832         printf("%d\n", i);
833
834         return correct;
835 }
836
837 static bool run_torture(int dummy)
838 {
839         struct cli_state *cli;
840         bool ret;
841
842         cli = current_cli;
843
844         smbXcli_conn_set_sockopt(cli->conn, sockops);
845
846         ret = rw_torture(cli);
847
848         if (!torture_close_connection(cli)) {
849                 ret = False;
850         }
851
852         return ret;
853 }
854
855 static bool rw_torture3(struct cli_state *c, char *lockfname)
856 {
857         uint16_t fnum = (uint16_t)-1;
858         unsigned int i = 0;
859         char buf[131072];
860         char buf_rd[131072];
861         unsigned count;
862         unsigned countprev = 0;
863         size_t sent = 0;
864         bool correct = True;
865         NTSTATUS status = NT_STATUS_OK;
866
867         srandom(1);
868         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
869         {
870                 SIVAL(buf, i, sys_random());
871         }
872
873         if (procnum == 0)
874         {
875                 status = cli_unlink(
876                         c, lockfname,
877                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
878                 if (!NT_STATUS_IS_OK(status)) {
879                         printf("unlink failed (%s) (normal, this file should "
880                                "not exist)\n", nt_errstr(status));
881                 }
882
883                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
884                                   DENY_NONE, &fnum);
885                 if (!NT_STATUS_IS_OK(status)) {
886                         printf("first open read/write of %s failed (%s)\n",
887                                         lockfname, nt_errstr(status));
888                         return False;
889                 }
890         }
891         else
892         {
893                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
894                 {
895                         status = cli_openx(c, lockfname, O_RDONLY, 
896                                          DENY_NONE, &fnum);
897                         if (NT_STATUS_IS_OK(status)) {
898                                 break;
899                         }
900                         smb_msleep(10);
901                 }
902                 if (!NT_STATUS_IS_OK(status)) {
903                         printf("second open read-only of %s failed (%s)\n",
904                                         lockfname, nt_errstr(status));
905                         return False;
906                 }
907         }
908
909         i = 0;
910         for (count = 0; count < sizeof(buf); count += sent)
911         {
912                 if (count >= countprev) {
913                         printf("%d %8d\r", i, count);
914                         fflush(stdout);
915                         i++;
916                         countprev += (sizeof(buf) / 20);
917                 }
918
919                 if (procnum == 0)
920                 {
921                         sent = ((unsigned)sys_random()%(20))+ 1;
922                         if (sent > sizeof(buf) - count)
923                         {
924                                 sent = sizeof(buf) - count;
925                         }
926
927                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
928                                               count, sent, NULL);
929                         if (!NT_STATUS_IS_OK(status)) {
930                                 printf("write failed (%s)\n",
931                                        nt_errstr(status));
932                                 correct = False;
933                         }
934                 }
935                 else
936                 {
937                         status = cli_read(c, fnum, buf_rd+count, count,
938                                           sizeof(buf)-count, &sent);
939                         if(!NT_STATUS_IS_OK(status)) {
940                                 printf("read failed offset:%d size:%ld (%s)\n",
941                                        count, (unsigned long)sizeof(buf)-count,
942                                        nt_errstr(status));
943                                 correct = False;
944                                 sent = 0;
945                         } else if (sent > 0) {
946                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
947                                 {
948                                         printf("read/write compare failed\n");
949                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
950                                         correct = False;
951                                         break;
952                                 }
953                         }
954                 }
955
956         }
957
958         status = cli_close(c, fnum);
959         if (!NT_STATUS_IS_OK(status)) {
960                 printf("close failed (%s)\n", nt_errstr(status));
961                 correct = False;
962         }
963
964         return correct;
965 }
966
967 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
968 {
969         const char *lockfname = "\\torture2.lck";
970         uint16_t fnum1;
971         uint16_t fnum2;
972         int i;
973         char buf[131072];
974         char buf_rd[131072];
975         bool correct = True;
976         size_t bytes_read;
977         NTSTATUS status;
978
979         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
980         if (!NT_STATUS_IS_OK(status)) {
981                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
982         }
983
984         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
985                           DENY_NONE, &fnum1);
986         if (!NT_STATUS_IS_OK(status)) {
987                 printf("first open read/write of %s failed (%s)\n",
988                                 lockfname, nt_errstr(status));
989                 return False;
990         }
991
992         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
993         if (!NT_STATUS_IS_OK(status)) {
994                 printf("second open read-only of %s failed (%s)\n",
995                                 lockfname, nt_errstr(status));
996                 cli_close(c1, fnum1);
997                 return False;
998         }
999
1000         for (i = 0; i < torture_numops; i++)
1001         {
1002                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1003                 if (i % 10 == 0) {
1004                         printf("%d\r", i); fflush(stdout);
1005                 }
1006
1007                 generate_random_buffer((unsigned char *)buf, buf_size);
1008
1009                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1010                                       buf_size, NULL);
1011                 if (!NT_STATUS_IS_OK(status)) {
1012                         printf("write failed (%s)\n", nt_errstr(status));
1013                         correct = False;
1014                         break;
1015                 }
1016
1017                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1018                 if(!NT_STATUS_IS_OK(status)) {
1019                         printf("read failed (%s)\n", nt_errstr(status));
1020                         correct = false;
1021                         break;
1022                 } else if (bytes_read != buf_size) {
1023                         printf("read failed\n");
1024                         printf("read %ld, expected %ld\n",
1025                                (unsigned long)bytes_read,
1026                                (unsigned long)buf_size); 
1027                         correct = False;
1028                         break;
1029                 }
1030
1031                 if (memcmp(buf_rd, buf, buf_size) != 0)
1032                 {
1033                         printf("read/write compare failed\n");
1034                         correct = False;
1035                         break;
1036                 }
1037         }
1038
1039         status = cli_close(c2, fnum2);
1040         if (!NT_STATUS_IS_OK(status)) {
1041                 printf("close failed (%s)\n", nt_errstr(status));
1042                 correct = False;
1043         }
1044
1045         status = cli_close(c1, fnum1);
1046         if (!NT_STATUS_IS_OK(status)) {
1047                 printf("close failed (%s)\n", nt_errstr(status));
1048                 correct = False;
1049         }
1050
1051         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1052         if (!NT_STATUS_IS_OK(status)) {
1053                 printf("unlink failed (%s)\n", nt_errstr(status));
1054                 correct = False;
1055         }
1056
1057         return correct;
1058 }
1059
1060 static bool run_readwritetest(int dummy)
1061 {
1062         struct cli_state *cli1, *cli2;
1063         bool test1, test2 = False;
1064
1065         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1066                 return False;
1067         }
1068         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1069         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1070
1071         printf("starting readwritetest\n");
1072
1073         test1 = rw_torture2(cli1, cli2);
1074         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1075
1076         if (test1) {
1077                 test2 = rw_torture2(cli1, cli1);
1078                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1079         }
1080
1081         if (!torture_close_connection(cli1)) {
1082                 test1 = False;
1083         }
1084
1085         if (!torture_close_connection(cli2)) {
1086                 test2 = False;
1087         }
1088
1089         return (test1 && test2);
1090 }
1091
1092 static bool run_readwritemulti(int dummy)
1093 {
1094         struct cli_state *cli;
1095         bool test;
1096
1097         cli = current_cli;
1098
1099         smbXcli_conn_set_sockopt(cli->conn, sockops);
1100
1101         printf("run_readwritemulti: fname %s\n", randomfname);
1102         test = rw_torture3(cli, randomfname);
1103
1104         if (!torture_close_connection(cli)) {
1105                 test = False;
1106         }
1107
1108         return test;
1109 }
1110
1111 static bool run_readwritelarge_internal(void)
1112 {
1113         static struct cli_state *cli1;
1114         uint16_t fnum1;
1115         const char *lockfname = "\\large.dat";
1116         off_t fsize;
1117         char buf[126*1024];
1118         bool correct = True;
1119         NTSTATUS status;
1120
1121         if (!torture_open_connection(&cli1, 0)) {
1122                 return False;
1123         }
1124         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1125         memset(buf,'\0',sizeof(buf));
1126
1127         printf("starting readwritelarge_internal\n");
1128
1129         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1130
1131         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1132                           DENY_NONE, &fnum1);
1133         if (!NT_STATUS_IS_OK(status)) {
1134                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1135                 return False;
1136         }
1137
1138         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1139
1140         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1141                                      NULL, NULL, NULL);
1142         if (!NT_STATUS_IS_OK(status)) {
1143                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1144                 correct = False;
1145         }
1146
1147         if (fsize == sizeof(buf))
1148                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1149                        (unsigned long)fsize);
1150         else {
1151                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1152                        (unsigned long)fsize);
1153                 correct = False;
1154         }
1155
1156         status = cli_close(cli1, fnum1);
1157         if (!NT_STATUS_IS_OK(status)) {
1158                 printf("close failed (%s)\n", nt_errstr(status));
1159                 correct = False;
1160         }
1161
1162         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1163         if (!NT_STATUS_IS_OK(status)) {
1164                 printf("unlink failed (%s)\n", nt_errstr(status));
1165                 correct = False;
1166         }
1167
1168         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1169                           DENY_NONE, &fnum1);
1170         if (!NT_STATUS_IS_OK(status)) {
1171                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1172                 return False;
1173         }
1174
1175         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1176
1177         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1178                                      NULL, NULL, NULL);
1179         if (!NT_STATUS_IS_OK(status)) {
1180                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1181                 correct = False;
1182         }
1183
1184         if (fsize == sizeof(buf))
1185                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1186                        (unsigned long)fsize);
1187         else {
1188                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1189                        (unsigned long)fsize);
1190                 correct = False;
1191         }
1192
1193         status = cli_close(cli1, fnum1);
1194         if (!NT_STATUS_IS_OK(status)) {
1195                 printf("close failed (%s)\n", nt_errstr(status));
1196                 correct = False;
1197         }
1198
1199         if (!torture_close_connection(cli1)) {
1200                 correct = False;
1201         }
1202         return correct;
1203 }
1204
1205 static bool run_readwritelarge(int dummy)
1206 {
1207         return run_readwritelarge_internal();
1208 }
1209
1210 static bool run_readwritelarge_signtest(int dummy)
1211 {
1212         bool ret;
1213         signing_state = SMB_SIGNING_REQUIRED;
1214         ret = run_readwritelarge_internal();
1215         signing_state = SMB_SIGNING_DEFAULT;
1216         return ret;
1217 }
1218
1219 int line_count = 0;
1220 int nbio_id;
1221
1222 #define ival(s) strtol(s, NULL, 0)
1223
1224 /* run a test that simulates an approximate netbench client load */
1225 static bool run_netbench(int client)
1226 {
1227         struct cli_state *cli;
1228         int i;
1229         char line[1024];
1230         char cname[20];
1231         FILE *f;
1232         const char *params[20];
1233         bool correct = True;
1234
1235         cli = current_cli;
1236
1237         nbio_id = client;
1238
1239         smbXcli_conn_set_sockopt(cli->conn, sockops);
1240
1241         nb_setup(cli);
1242
1243         slprintf(cname,sizeof(cname)-1, "client%d", client);
1244
1245         f = fopen(client_txt, "r");
1246
1247         if (!f) {
1248                 perror(client_txt);
1249                 return False;
1250         }
1251
1252         while (fgets(line, sizeof(line)-1, f)) {
1253                 char *saveptr;
1254                 line_count++;
1255
1256                 line[strlen(line)-1] = 0;
1257
1258                 /* printf("[%d] %s\n", line_count, line); */
1259
1260                 all_string_sub(line,"client1", cname, sizeof(line));
1261
1262                 /* parse the command parameters */
1263                 params[0] = strtok_r(line, " ", &saveptr);
1264                 i = 0;
1265                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1266
1267                 params[i] = "";
1268
1269                 if (i < 2) continue;
1270
1271                 if (!strncmp(params[0],"SMB", 3)) {
1272                         printf("ERROR: You are using a dbench 1 load file\n");
1273                         exit(1);
1274                 }
1275
1276                 if (!strcmp(params[0],"NTCreateX")) {
1277                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1278                                    ival(params[4]));
1279                 } else if (!strcmp(params[0],"Close")) {
1280                         nb_close(ival(params[1]));
1281                 } else if (!strcmp(params[0],"Rename")) {
1282                         nb_rename(params[1], params[2]);
1283                 } else if (!strcmp(params[0],"Unlink")) {
1284                         nb_unlink(params[1]);
1285                 } else if (!strcmp(params[0],"Deltree")) {
1286                         nb_deltree(params[1]);
1287                 } else if (!strcmp(params[0],"Rmdir")) {
1288                         nb_rmdir(params[1]);
1289                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1290                         nb_qpathinfo(params[1]);
1291                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1292                         nb_qfileinfo(ival(params[1]));
1293                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1294                         nb_qfsinfo(ival(params[1]));
1295                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1296                         nb_findfirst(params[1]);
1297                 } else if (!strcmp(params[0],"WriteX")) {
1298                         nb_writex(ival(params[1]), 
1299                                   ival(params[2]), ival(params[3]), ival(params[4]));
1300                 } else if (!strcmp(params[0],"ReadX")) {
1301                         nb_readx(ival(params[1]), 
1302                                   ival(params[2]), ival(params[3]), ival(params[4]));
1303                 } else if (!strcmp(params[0],"Flush")) {
1304                         nb_flush(ival(params[1]));
1305                 } else {
1306                         printf("Unknown operation %s\n", params[0]);
1307                         exit(1);
1308                 }
1309         }
1310         fclose(f);
1311
1312         nb_cleanup();
1313
1314         if (!torture_close_connection(cli)) {
1315                 correct = False;
1316         }
1317
1318         return correct;
1319 }
1320
1321
1322 /* run a test that simulates an approximate netbench client load */
1323 static bool run_nbench(int dummy)
1324 {
1325         double t;
1326         bool correct = True;
1327
1328         nbio_shmem(torture_nprocs);
1329
1330         nbio_id = -1;
1331
1332         signal(SIGALRM, nb_alarm);
1333         alarm(1);
1334         t = create_procs(run_netbench, &correct);
1335         alarm(0);
1336
1337         printf("\nThroughput %g MB/sec\n", 
1338                1.0e-6 * nbio_total() / t);
1339         return correct;
1340 }
1341
1342
1343 /*
1344   This test checks for two things:
1345
1346   1) correct support for retaining locks over a close (ie. the server
1347      must not use posix semantics)
1348   2) support for lock timeouts
1349  */
1350 static bool run_locktest1(int dummy)
1351 {
1352         struct cli_state *cli1, *cli2;
1353         const char *fname = "\\lockt1.lck";
1354         uint16_t fnum1, fnum2, fnum3;
1355         time_t t1, t2;
1356         unsigned lock_timeout;
1357         NTSTATUS status;
1358
1359         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1360                 return False;
1361         }
1362         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1363         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1364
1365         printf("starting locktest1\n");
1366
1367         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1368
1369         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1370                           &fnum1);
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1373                 return False;
1374         }
1375
1376         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1377         if (!NT_STATUS_IS_OK(status)) {
1378                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1379                 return False;
1380         }
1381
1382         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1383         if (!NT_STATUS_IS_OK(status)) {
1384                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1385                 return False;
1386         }
1387
1388         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1389         if (!NT_STATUS_IS_OK(status)) {
1390                 printf("lock1 failed (%s)\n", nt_errstr(status));
1391                 return false;
1392         }
1393
1394         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1395         if (NT_STATUS_IS_OK(status)) {
1396                 printf("lock2 succeeded! This is a locking bug\n");
1397                 return false;
1398         } else {
1399                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1400                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1401                         return false;
1402                 }
1403         }
1404
1405         lock_timeout = (1 + (random() % 20));
1406         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1407         t1 = time(NULL);
1408         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1409         if (NT_STATUS_IS_OK(status)) {
1410                 printf("lock3 succeeded! This is a locking bug\n");
1411                 return false;
1412         } else {
1413                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1414                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1415                         return false;
1416                 }
1417         }
1418         t2 = time(NULL);
1419
1420         if (ABS(t2 - t1) < lock_timeout-1) {
1421                 printf("error: This server appears not to support timed lock requests\n");
1422         }
1423
1424         printf("server slept for %u seconds for a %u second timeout\n",
1425                (unsigned int)(t2-t1), lock_timeout);
1426
1427         status = cli_close(cli1, fnum2);
1428         if (!NT_STATUS_IS_OK(status)) {
1429                 printf("close1 failed (%s)\n", nt_errstr(status));
1430                 return False;
1431         }
1432
1433         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1434         if (NT_STATUS_IS_OK(status)) {
1435                 printf("lock4 succeeded! This is a locking bug\n");
1436                 return false;
1437         } else {
1438                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1439                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1440                         return false;
1441                 }
1442         }
1443
1444         status = cli_close(cli1, fnum1);
1445         if (!NT_STATUS_IS_OK(status)) {
1446                 printf("close2 failed (%s)\n", nt_errstr(status));
1447                 return False;
1448         }
1449
1450         status = cli_close(cli2, fnum3);
1451         if (!NT_STATUS_IS_OK(status)) {
1452                 printf("close3 failed (%s)\n", nt_errstr(status));
1453                 return False;
1454         }
1455
1456         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1457         if (!NT_STATUS_IS_OK(status)) {
1458                 printf("unlink failed (%s)\n", nt_errstr(status));
1459                 return False;
1460         }
1461
1462
1463         if (!torture_close_connection(cli1)) {
1464                 return False;
1465         }
1466
1467         if (!torture_close_connection(cli2)) {
1468                 return False;
1469         }
1470
1471         printf("Passed locktest1\n");
1472         return True;
1473 }
1474
1475 /*
1476   this checks to see if a secondary tconx can use open files from an
1477   earlier tconx
1478  */
1479 static bool run_tcon_test(int dummy)
1480 {
1481         static struct cli_state *cli;
1482         const char *fname = "\\tcontest.tmp";
1483         uint16_t fnum1;
1484         uint32_t cnum1, cnum2, cnum3;
1485         struct smbXcli_tcon *orig_tcon = NULL;
1486         char *orig_share = NULL;
1487         uint16_t vuid1, vuid2;
1488         char buf[4];
1489         bool ret = True;
1490         NTSTATUS status;
1491
1492         memset(buf, '\0', sizeof(buf));
1493
1494         if (!torture_open_connection(&cli, 0)) {
1495                 return False;
1496         }
1497         smbXcli_conn_set_sockopt(cli->conn, sockops);
1498
1499         printf("starting tcontest\n");
1500
1501         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1502
1503         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1504         if (!NT_STATUS_IS_OK(status)) {
1505                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1506                 return False;
1507         }
1508
1509         cnum1 = cli_state_get_tid(cli);
1510         vuid1 = cli_state_get_uid(cli);
1511
1512         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1513         if (!NT_STATUS_IS_OK(status)) {
1514                 printf("initial write failed (%s)", nt_errstr(status));
1515                 return False;
1516         }
1517
1518         cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1519
1520         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1521         if (!NT_STATUS_IS_OK(status)) {
1522                 printf("%s refused 2nd tree connect (%s)\n", host,
1523                        nt_errstr(status));
1524                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1525                 cli_shutdown(cli);
1526                 return False;
1527         }
1528
1529         cnum2 = cli_state_get_tid(cli);
1530         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1531         vuid2 = cli_state_get_uid(cli) + 1;
1532
1533         /* try a write with the wrong tid */
1534         cli_state_set_tid(cli, cnum2);
1535
1536         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1537         if (NT_STATUS_IS_OK(status)) {
1538                 printf("* server allows write with wrong TID\n");
1539                 ret = False;
1540         } else {
1541                 printf("server fails write with wrong TID : %s\n",
1542                        nt_errstr(status));
1543         }
1544
1545
1546         /* try a write with an invalid tid */
1547         cli_state_set_tid(cli, cnum3);
1548
1549         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1550         if (NT_STATUS_IS_OK(status)) {
1551                 printf("* server allows write with invalid TID\n");
1552                 ret = False;
1553         } else {
1554                 printf("server fails write with invalid TID : %s\n",
1555                        nt_errstr(status));
1556         }
1557
1558         /* try a write with an invalid vuid */
1559         cli_state_set_uid(cli, vuid2);
1560         cli_state_set_tid(cli, cnum1);
1561
1562         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1563         if (NT_STATUS_IS_OK(status)) {
1564                 printf("* server allows write with invalid VUID\n");
1565                 ret = False;
1566         } else {
1567                 printf("server fails write with invalid VUID : %s\n",
1568                        nt_errstr(status));
1569         }
1570
1571         cli_state_set_tid(cli, cnum1);
1572         cli_state_set_uid(cli, vuid1);
1573
1574         status = cli_close(cli, fnum1);
1575         if (!NT_STATUS_IS_OK(status)) {
1576                 printf("close failed (%s)\n", nt_errstr(status));
1577                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1578                 cli_shutdown(cli);
1579                 return False;
1580         }
1581
1582         cli_state_set_tid(cli, cnum2);
1583
1584         status = cli_tdis(cli);
1585         if (!NT_STATUS_IS_OK(status)) {
1586                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1587                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1588                 cli_shutdown(cli);
1589                 return False;
1590         }
1591
1592         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1593
1594         cli_state_set_tid(cli, cnum1);
1595
1596         if (!torture_close_connection(cli)) {
1597                 return False;
1598         }
1599
1600         return ret;
1601 }
1602
1603
1604 /*
1605  checks for old style tcon support
1606  */
1607 static bool run_tcon2_test(int dummy)
1608 {
1609         static struct cli_state *cli;
1610         uint16_t cnum, max_xmit;
1611         char *service;
1612         NTSTATUS status;
1613
1614         if (!torture_open_connection(&cli, 0)) {
1615                 return False;
1616         }
1617         smbXcli_conn_set_sockopt(cli->conn, sockops);
1618
1619         printf("starting tcon2 test\n");
1620
1621         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1622                 return false;
1623         }
1624
1625         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1626
1627         SAFE_FREE(service);
1628
1629         if (!NT_STATUS_IS_OK(status)) {
1630                 printf("tcon2 failed : %s\n", nt_errstr(status));
1631         } else {
1632                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1633                        (int)max_xmit, (int)cnum);
1634         }
1635
1636         if (!torture_close_connection(cli)) {
1637                 return False;
1638         }
1639
1640         printf("Passed tcon2 test\n");
1641         return True;
1642 }
1643
1644 static bool tcon_devtest(struct cli_state *cli,
1645                          const char *myshare, const char *devtype,
1646                          const char *return_devtype,
1647                          NTSTATUS expected_error)
1648 {
1649         NTSTATUS status;
1650         bool ret;
1651
1652         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1653
1654         if (NT_STATUS_IS_OK(expected_error)) {
1655                 if (NT_STATUS_IS_OK(status)) {
1656                         if (return_devtype != NULL &&
1657                             strequal(cli->dev, return_devtype)) {
1658                                 ret = True;
1659                         } else { 
1660                                 printf("tconX to share %s with type %s "
1661                                        "succeeded but returned the wrong "
1662                                        "device type (got [%s] but should have got [%s])\n",
1663                                        myshare, devtype, cli->dev, return_devtype);
1664                                 ret = False;
1665                         }
1666                 } else {
1667                         printf("tconX to share %s with type %s "
1668                                "should have succeeded but failed\n",
1669                                myshare, devtype);
1670                         ret = False;
1671                 }
1672                 cli_tdis(cli);
1673         } else {
1674                 if (NT_STATUS_IS_OK(status)) {
1675                         printf("tconx to share %s with type %s "
1676                                "should have failed but succeeded\n",
1677                                myshare, devtype);
1678                         ret = False;
1679                 } else {
1680                         if (NT_STATUS_EQUAL(status, expected_error)) {
1681                                 ret = True;
1682                         } else {
1683                                 printf("Returned unexpected error\n");
1684                                 ret = False;
1685                         }
1686                 }
1687         }
1688         return ret;
1689 }
1690
1691 /*
1692  checks for correct tconX support
1693  */
1694 static bool run_tcon_devtype_test(int dummy)
1695 {
1696         static struct cli_state *cli1 = NULL;
1697         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1698         NTSTATUS status;
1699         bool ret = True;
1700
1701         status = cli_full_connection_creds(&cli1,
1702                                            myname,
1703                                            host,
1704                                            NULL, /* dest_ss */
1705                                            port_to_use,
1706                                            NULL, /* service */
1707                                            NULL, /* service_type */
1708                                            torture_creds,
1709                                            flags);
1710
1711         if (!NT_STATUS_IS_OK(status)) {
1712                 printf("could not open connection\n");
1713                 return False;
1714         }
1715
1716         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1717                 ret = False;
1718
1719         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1720                 ret = False;
1721
1722         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1723                 ret = False;
1724
1725         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1726                 ret = False;
1727
1728         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1729                 ret = False;
1730
1731         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1732                 ret = False;
1733
1734         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1735                 ret = False;
1736
1737         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1738                 ret = False;
1739
1740         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741                 ret = False;
1742
1743         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1744                 ret = False;
1745
1746         cli_shutdown(cli1);
1747
1748         if (ret)
1749                 printf("Passed tcondevtest\n");
1750
1751         return ret;
1752 }
1753
1754
1755 /*
1756   This test checks that 
1757
1758   1) the server supports multiple locking contexts on the one SMB
1759   connection, distinguished by PID.  
1760
1761   2) the server correctly fails overlapping locks made by the same PID (this
1762      goes against POSIX behaviour, which is why it is tricky to implement)
1763
1764   3) the server denies unlock requests by an incorrect client PID
1765 */
1766 static bool run_locktest2(int dummy)
1767 {
1768         static struct cli_state *cli;
1769         const char *fname = "\\lockt2.lck";
1770         uint16_t fnum1, fnum2, fnum3;
1771         bool correct = True;
1772         NTSTATUS status;
1773
1774         if (!torture_open_connection(&cli, 0)) {
1775                 return False;
1776         }
1777
1778         smbXcli_conn_set_sockopt(cli->conn, sockops);
1779
1780         printf("starting locktest2\n");
1781
1782         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1783
1784         cli_setpid(cli, 1);
1785
1786         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1787         if (!NT_STATUS_IS_OK(status)) {
1788                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1789                 return False;
1790         }
1791
1792         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1793         if (!NT_STATUS_IS_OK(status)) {
1794                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1795                 return False;
1796         }
1797
1798         cli_setpid(cli, 2);
1799
1800         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1801         if (!NT_STATUS_IS_OK(status)) {
1802                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1803                 return False;
1804         }
1805
1806         cli_setpid(cli, 1);
1807
1808         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1809         if (!NT_STATUS_IS_OK(status)) {
1810                 printf("lock1 failed (%s)\n", nt_errstr(status));
1811                 return false;
1812         }
1813
1814         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1815         if (NT_STATUS_IS_OK(status)) {
1816                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1817                 correct = false;
1818         } else {
1819                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1820                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1821                         return false;
1822                 }
1823         }
1824
1825         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1826         if (NT_STATUS_IS_OK(status)) {
1827                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1828                 correct = false;
1829         } else {
1830                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1831                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1832                         return false;
1833                 }
1834         }
1835
1836         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1837         if (NT_STATUS_IS_OK(status)) {
1838                 printf("READ lock2 succeeded! This is a locking bug\n");
1839                 correct = false;
1840         } else {
1841                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1842                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1843                         return false;
1844                 }
1845         }
1846
1847         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1848         if (!NT_STATUS_IS_OK(status)) {
1849                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1850         }
1851         cli_setpid(cli, 2);
1852         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1853                 printf("unlock at 100 succeeded! This is a locking bug\n");
1854                 correct = False;
1855         }
1856
1857         status = cli_unlock(cli, fnum1, 0, 4);
1858         if (NT_STATUS_IS_OK(status)) {
1859                 printf("unlock1 succeeded! This is a locking bug\n");
1860                 correct = false;
1861         } else {
1862                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1863                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1864                         return false;
1865                 }
1866         }
1867
1868         status = cli_unlock(cli, fnum1, 0, 8);
1869         if (NT_STATUS_IS_OK(status)) {
1870                 printf("unlock2 succeeded! This is a locking bug\n");
1871                 correct = false;
1872         } else {
1873                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1874                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1875                         return false;
1876                 }
1877         }
1878
1879         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1880         if (NT_STATUS_IS_OK(status)) {
1881                 printf("lock3 succeeded! This is a locking bug\n");
1882                 correct = false;
1883         } else {
1884                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1885                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1886                         return false;
1887                 }
1888         }
1889
1890         cli_setpid(cli, 1);
1891
1892         status = cli_close(cli, fnum1);
1893         if (!NT_STATUS_IS_OK(status)) {
1894                 printf("close1 failed (%s)\n", nt_errstr(status));
1895                 return False;
1896         }
1897
1898         status = cli_close(cli, fnum2);
1899         if (!NT_STATUS_IS_OK(status)) {
1900                 printf("close2 failed (%s)\n", nt_errstr(status));
1901                 return False;
1902         }
1903
1904         status = cli_close(cli, fnum3);
1905         if (!NT_STATUS_IS_OK(status)) {
1906                 printf("close3 failed (%s)\n", nt_errstr(status));
1907                 return False;
1908         }
1909
1910         if (!torture_close_connection(cli)) {
1911                 correct = False;
1912         }
1913
1914         printf("locktest2 finished\n");
1915
1916         return correct;
1917 }
1918
1919
1920 /*
1921   This test checks that 
1922
1923   1) the server supports the full offset range in lock requests
1924 */
1925 static bool run_locktest3(int dummy)
1926 {
1927         static struct cli_state *cli1, *cli2;
1928         const char *fname = "\\lockt3.lck";
1929         uint16_t fnum1, fnum2;
1930         int i;
1931         uint32_t offset;
1932         bool correct = True;
1933         NTSTATUS status;
1934
1935 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1936
1937         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1938                 return False;
1939         }
1940         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1941         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1942
1943         printf("starting locktest3\n");
1944
1945         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1946
1947         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1948                          &fnum1);
1949         if (!NT_STATUS_IS_OK(status)) {
1950                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1951                 return False;
1952         }
1953
1954         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1955         if (!NT_STATUS_IS_OK(status)) {
1956                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1957                 return False;
1958         }
1959
1960         for (offset=i=0;i<torture_numops;i++) {
1961                 NEXT_OFFSET;
1962
1963                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1964                 if (!NT_STATUS_IS_OK(status)) {
1965                         printf("lock1 %d failed (%s)\n", 
1966                                i,
1967                                nt_errstr(status));
1968                         return False;
1969                 }
1970
1971                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1972                 if (!NT_STATUS_IS_OK(status)) {
1973                         printf("lock2 %d failed (%s)\n", 
1974                                i,
1975                                nt_errstr(status));
1976                         return False;
1977                 }
1978         }
1979
1980         for (offset=i=0;i<torture_numops;i++) {
1981                 NEXT_OFFSET;
1982
1983                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1984                 if (NT_STATUS_IS_OK(status)) {
1985                         printf("error: lock1 %d succeeded!\n", i);
1986                         return False;
1987                 }
1988
1989                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1990                 if (NT_STATUS_IS_OK(status)) {
1991                         printf("error: lock2 %d succeeded!\n", i);
1992                         return False;
1993                 }
1994
1995                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1996                 if (NT_STATUS_IS_OK(status)) {
1997                         printf("error: lock3 %d succeeded!\n", i);
1998                         return False;
1999                 }
2000
2001                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2002                 if (NT_STATUS_IS_OK(status)) {
2003                         printf("error: lock4 %d succeeded!\n", i);
2004                         return False;
2005                 }
2006         }
2007
2008         for (offset=i=0;i<torture_numops;i++) {
2009                 NEXT_OFFSET;
2010
2011                 status = cli_unlock(cli1, fnum1, offset-1, 1);
2012                 if (!NT_STATUS_IS_OK(status)) {
2013                         printf("unlock1 %d failed (%s)\n", 
2014                                i,
2015                                nt_errstr(status));
2016                         return False;
2017                 }
2018
2019                 status = cli_unlock(cli2, fnum2, offset-2, 1);
2020                 if (!NT_STATUS_IS_OK(status)) {
2021                         printf("unlock2 %d failed (%s)\n", 
2022                                i,
2023                                nt_errstr(status));
2024                         return False;
2025                 }
2026         }
2027
2028         status = cli_close(cli1, fnum1);
2029         if (!NT_STATUS_IS_OK(status)) {
2030                 printf("close1 failed (%s)\n", nt_errstr(status));
2031                 return False;
2032         }
2033
2034         status = cli_close(cli2, fnum2);
2035         if (!NT_STATUS_IS_OK(status)) {
2036                 printf("close2 failed (%s)\n", nt_errstr(status));
2037                 return False;
2038         }
2039
2040         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2041         if (!NT_STATUS_IS_OK(status)) {
2042                 printf("unlink failed (%s)\n", nt_errstr(status));
2043                 return False;
2044         }
2045
2046         if (!torture_close_connection(cli1)) {
2047                 correct = False;
2048         }
2049
2050         if (!torture_close_connection(cli2)) {
2051                 correct = False;
2052         }
2053
2054         printf("finished locktest3\n");
2055
2056         return correct;
2057 }
2058
2059 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2060                            char *buf, off_t offset, size_t size,
2061                            size_t *nread, size_t expect)
2062 {
2063         NTSTATUS status;
2064         size_t l_nread;
2065
2066         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2067
2068         if(!NT_STATUS_IS_OK(status)) {
2069                 return false;
2070         } else if (l_nread != expect) {
2071                 return false;
2072         }
2073
2074         if (nread) {
2075                 *nread = l_nread;
2076         }
2077
2078         return true;
2079 }
2080
2081 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2082         printf("** "); correct = False; \
2083         }
2084
2085 /*
2086   looks at overlapping locks
2087 */
2088 static bool run_locktest4(int dummy)
2089 {
2090         static struct cli_state *cli1, *cli2;
2091         const char *fname = "\\lockt4.lck";
2092         uint16_t fnum1, fnum2, f;
2093         bool ret;
2094         char buf[1000];
2095         bool correct = True;
2096         NTSTATUS status;
2097
2098         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2099                 return False;
2100         }
2101
2102         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2103         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2104
2105         printf("starting locktest4\n");
2106
2107         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2108
2109         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2110         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2111
2112         memset(buf, 0, sizeof(buf));
2113
2114         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2115                               NULL);
2116         if (!NT_STATUS_IS_OK(status)) {
2117                 printf("Failed to create file: %s\n", nt_errstr(status));
2118                 correct = False;
2119                 goto fail;
2120         }
2121
2122         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2123               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2124         EXPECTED(ret, False);
2125         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2126
2127         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2128               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2129         EXPECTED(ret, True);
2130         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2131
2132         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2133               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2134         EXPECTED(ret, False);
2135         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2136
2137         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2138               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2139         EXPECTED(ret, True);
2140         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2141
2142         ret = (cli_setpid(cli1, 1),
2143               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2144               (cli_setpid(cli1, 2),
2145               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2146         EXPECTED(ret, False);
2147         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2148
2149         ret = (cli_setpid(cli1, 1),
2150               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2151               (cli_setpid(cli1, 2),
2152               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2153         EXPECTED(ret, True);
2154         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2155
2156         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2157               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2158         EXPECTED(ret, True);
2159         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2160
2161         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2162               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2163         EXPECTED(ret, False);
2164         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2165
2166         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2167               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2168         EXPECTED(ret, False);
2169         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2170
2171         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2172               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2173         EXPECTED(ret, True);
2174         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2175
2176         ret = (cli_setpid(cli1, 1),
2177              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2178              (cli_setpid(cli1, 2),
2179              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2180         EXPECTED(ret, False);
2181         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2182
2183         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2184               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2185               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2186         EXPECTED(ret, False);
2187         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2188
2189
2190         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2191               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2192         EXPECTED(ret, False);
2193         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2194
2195         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2196         ret = NT_STATUS_IS_OK(status);
2197         if (ret) {
2198                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2199                                       NULL);
2200                 ret = NT_STATUS_IS_OK(status);
2201         }
2202         EXPECTED(ret, False);
2203         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2204
2205
2206         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2207               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2208               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2209               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2210         EXPECTED(ret, True);
2211         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2212
2213
2214         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2215               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2216               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2217               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2218               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2219                                              150, 4, NULL))) &&
2220               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2221         EXPECTED(ret, True);
2222         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2223
2224         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2225               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2226               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2227                                            160, 4, NULL)) &&
2228               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2229         EXPECTED(ret, True);
2230         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2231
2232         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2233               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2234               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2235                                            170, 4, NULL)) &&
2236               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2237         EXPECTED(ret, True);
2238         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2239
2240         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2241               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2242               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2243               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2244                                             190, 4, NULL)) &&
2245               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2246         EXPECTED(ret, True);
2247         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2248
2249         cli_close(cli1, fnum1);
2250         cli_close(cli2, fnum2);
2251         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2252         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2253         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2254               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2255               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2256               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2257               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2258         cli_close(cli1, f);
2259         cli_close(cli1, fnum1);
2260         EXPECTED(ret, True);
2261         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2262
2263  fail:
2264         cli_close(cli1, fnum1);
2265         cli_close(cli2, fnum2);
2266         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2267         torture_close_connection(cli1);
2268         torture_close_connection(cli2);
2269
2270         printf("finished locktest4\n");
2271         return correct;
2272 }
2273
2274 /*
2275   looks at lock upgrade/downgrade.
2276 */
2277 static bool run_locktest5(int dummy)
2278 {
2279         static struct cli_state *cli1, *cli2;
2280         const char *fname = "\\lockt5.lck";
2281         uint16_t fnum1, fnum2, fnum3;
2282         bool ret;
2283         char buf[1000];
2284         bool correct = True;
2285         NTSTATUS status;
2286
2287         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2288                 return False;
2289         }
2290
2291         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2292         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2293
2294         printf("starting locktest5\n");
2295
2296         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2297
2298         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2299         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2300         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2301
2302         memset(buf, 0, sizeof(buf));
2303
2304         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2305                               NULL);
2306         if (!NT_STATUS_IS_OK(status)) {
2307                 printf("Failed to create file: %s\n", nt_errstr(status));
2308                 correct = False;
2309                 goto fail;
2310         }
2311
2312         /* Check for NT bug... */
2313         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2314               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2315         cli_close(cli1, fnum1);
2316         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2317         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2318         ret = NT_STATUS_IS_OK(status);
2319         EXPECTED(ret, True);
2320         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2321         cli_close(cli1, fnum1);
2322         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2323         cli_unlock(cli1, fnum3, 0, 1);
2324
2325         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2326               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2327         EXPECTED(ret, True);
2328         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2329
2330         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2331         ret = NT_STATUS_IS_OK(status);
2332         EXPECTED(ret, False);
2333
2334         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2335
2336         /* Unlock the process 2 lock. */
2337         cli_unlock(cli2, fnum2, 0, 4);
2338
2339         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2340         ret = NT_STATUS_IS_OK(status);
2341         EXPECTED(ret, False);
2342
2343         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2344
2345         /* Unlock the process 1 fnum3 lock. */
2346         cli_unlock(cli1, fnum3, 0, 4);
2347
2348         /* Stack 2 more locks here. */
2349         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2350               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2351
2352         EXPECTED(ret, True);
2353         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2354
2355         /* Unlock the first process lock, then check this was the WRITE lock that was
2356                 removed. */
2357
2358         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2359               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2360
2361         EXPECTED(ret, True);
2362         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2363
2364         /* Unlock the process 2 lock. */
2365         cli_unlock(cli2, fnum2, 0, 4);
2366
2367         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2368
2369         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2370                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2371                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2372
2373         EXPECTED(ret, True);
2374         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2375
2376         /* Ensure the next unlock fails. */
2377         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2378         EXPECTED(ret, False);
2379         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2380
2381         /* Ensure connection 2 can get a write lock. */
2382         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2383         ret = NT_STATUS_IS_OK(status);
2384         EXPECTED(ret, True);
2385
2386         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2387
2388
2389  fail:
2390         cli_close(cli1, fnum1);
2391         cli_close(cli2, fnum2);
2392         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2393         if (!torture_close_connection(cli1)) {
2394                 correct = False;
2395         }
2396         if (!torture_close_connection(cli2)) {
2397                 correct = False;
2398         }
2399
2400         printf("finished locktest5\n");
2401
2402         return correct;
2403 }
2404
2405 /*
2406   tries the unusual lockingX locktype bits
2407 */
2408 static bool run_locktest6(int dummy)
2409 {
2410         static struct cli_state *cli;
2411         const char *fname[1] = { "\\lock6.txt" };
2412         int i;
2413         uint16_t fnum;
2414         NTSTATUS status;
2415
2416         if (!torture_open_connection(&cli, 0)) {
2417                 return False;
2418         }
2419
2420         smbXcli_conn_set_sockopt(cli->conn, sockops);
2421
2422         printf("starting locktest6\n");
2423
2424         for (i=0;i<1;i++) {
2425                 printf("Testing %s\n", fname[i]);
2426
2427                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2428
2429                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2430                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2431                 cli_close(cli, fnum);
2432                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2433
2434                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2435                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2436                 cli_close(cli, fnum);
2437                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2438
2439                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2440         }
2441
2442         torture_close_connection(cli);
2443
2444         printf("finished locktest6\n");
2445         return True;
2446 }
2447
2448 static bool run_locktest7(int dummy)
2449 {
2450         struct cli_state *cli1;
2451         const char *fname = "\\lockt7.lck";
2452         uint16_t fnum1;
2453         char buf[200];
2454         bool correct = False;
2455         size_t nread;
2456         NTSTATUS status;
2457
2458         if (!torture_open_connection(&cli1, 0)) {
2459                 return False;
2460         }
2461
2462         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2463
2464         printf("starting locktest7\n");
2465
2466         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2467
2468         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2469
2470         memset(buf, 0, sizeof(buf));
2471
2472         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2473                               NULL);
2474         if (!NT_STATUS_IS_OK(status)) {
2475                 printf("Failed to create file: %s\n", nt_errstr(status));
2476                 goto fail;
2477         }
2478
2479         cli_setpid(cli1, 1);
2480
2481         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2482         if (!NT_STATUS_IS_OK(status)) {
2483                 printf("Unable to apply read lock on range 130:4, "
2484                        "error was %s\n", nt_errstr(status));
2485                 goto fail;
2486         } else {
2487                 printf("pid1 successfully locked range 130:4 for READ\n");
2488         }
2489
2490         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2491         if (!NT_STATUS_IS_OK(status)) {
2492                 printf("pid1 unable to read the range 130:4, error was %s\n",
2493                       nt_errstr(status));
2494                 goto fail;
2495         } else if (nread != 4) {
2496                 printf("pid1 unable to read the range 130:4, "
2497                        "recv %ld req %d\n", (unsigned long)nread, 4);
2498                 goto fail;
2499         } else {
2500                 printf("pid1 successfully read the range 130:4\n");
2501         }
2502
2503         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2504         if (!NT_STATUS_IS_OK(status)) {
2505                 printf("pid1 unable to write to the range 130:4, error was "
2506                        "%s\n", nt_errstr(status));
2507                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2508                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2509                         goto fail;
2510                 }
2511         } else {
2512                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2513                 goto fail;
2514         }
2515
2516         cli_setpid(cli1, 2);
2517
2518         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2519         if (!NT_STATUS_IS_OK(status)) {
2520                 printf("pid2 unable to read the range 130:4, error was %s\n",
2521                       nt_errstr(status));
2522                 goto fail;
2523         } else if (nread != 4) {
2524                 printf("pid2 unable to read the range 130:4, "
2525                        "recv %ld req %d\n", (unsigned long)nread, 4);
2526                 goto fail;
2527         } else {
2528                 printf("pid2 successfully read the range 130:4\n");
2529         }
2530
2531         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2532         if (!NT_STATUS_IS_OK(status)) {
2533                 printf("pid2 unable to write to the range 130:4, error was "
2534                        "%s\n", nt_errstr(status));
2535                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2536                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2537                         goto fail;
2538                 }
2539         } else {
2540                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2541                 goto fail;
2542         }
2543
2544         cli_setpid(cli1, 1);
2545         cli_unlock(cli1, fnum1, 130, 4);
2546
2547         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2548         if (!NT_STATUS_IS_OK(status)) {
2549                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2550                 goto fail;
2551         } else {
2552                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2553         }
2554
2555         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2556         if (!NT_STATUS_IS_OK(status)) {
2557                 printf("pid1 unable to read the range 130:4, error was %s\n",
2558                       nt_errstr(status));
2559                 goto fail;
2560         } else if (nread != 4) {
2561                 printf("pid1 unable to read the range 130:4, "
2562                        "recv %ld req %d\n", (unsigned long)nread, 4);
2563                 goto fail;
2564         } else {
2565                 printf("pid1 successfully read the range 130:4\n");
2566         }
2567
2568         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2569         if (!NT_STATUS_IS_OK(status)) {
2570                 printf("pid1 unable to write to the range 130:4, error was "
2571                        "%s\n", nt_errstr(status));
2572                 goto fail;
2573         } else {
2574                 printf("pid1 successfully wrote to the range 130:4\n");
2575         }
2576
2577         cli_setpid(cli1, 2);
2578
2579         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2580         if (!NT_STATUS_IS_OK(status)) {
2581                 printf("pid2 unable to read the range 130:4, error was "
2582                        "%s\n", nt_errstr(status));
2583                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2584                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2585                         goto fail;
2586                 }
2587         } else {
2588                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2589                        (unsigned long)nread);
2590                 goto fail;
2591         }
2592
2593         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2594         if (!NT_STATUS_IS_OK(status)) {
2595                 printf("pid2 unable to write to the range 130:4, error was "
2596                        "%s\n", nt_errstr(status));
2597                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2598                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2599                         goto fail;
2600                 }
2601         } else {
2602                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2603                 goto fail;
2604         }
2605
2606         cli_unlock(cli1, fnum1, 130, 0);
2607         correct = True;
2608
2609 fail:
2610         cli_close(cli1, fnum1);
2611         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2612         torture_close_connection(cli1);
2613
2614         printf("finished locktest7\n");
2615         return correct;
2616 }
2617
2618 /*
2619  * This demonstrates a problem with our use of GPFS share modes: A file
2620  * descriptor sitting in the pending close queue holding a GPFS share mode
2621  * blocks opening a file another time. Happens with Word 2007 temp files.
2622  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2623  * open is denied with NT_STATUS_SHARING_VIOLATION.
2624  */
2625
2626 static bool run_locktest8(int dummy)
2627 {
2628         struct cli_state *cli1;
2629         const char *fname = "\\lockt8.lck";
2630         uint16_t fnum1, fnum2;
2631         char buf[200];
2632         bool correct = False;
2633         NTSTATUS status;
2634
2635         if (!torture_open_connection(&cli1, 0)) {
2636                 return False;
2637         }
2638
2639         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2640
2641         printf("starting locktest8\n");
2642
2643         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2644
2645         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2646                           &fnum1);
2647         if (!NT_STATUS_IS_OK(status)) {
2648                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2649                 return false;
2650         }
2651
2652         memset(buf, 0, sizeof(buf));
2653
2654         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2655         if (!NT_STATUS_IS_OK(status)) {
2656                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2657                           nt_errstr(status));
2658                 goto fail;
2659         }
2660
2661         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2662         if (!NT_STATUS_IS_OK(status)) {
2663                 printf("Unable to apply read lock on range 1:1, error was "
2664                        "%s\n", nt_errstr(status));
2665                 goto fail;
2666         }
2667
2668         status = cli_close(cli1, fnum1);
2669         if (!NT_STATUS_IS_OK(status)) {
2670                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2671                 goto fail;
2672         }
2673
2674         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2675         if (!NT_STATUS_IS_OK(status)) {
2676                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2677                           nt_errstr(status));
2678                 goto fail;
2679         }
2680
2681         correct = true;
2682
2683 fail:
2684         cli_close(cli1, fnum1);
2685         cli_close(cli1, fnum2);
2686         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2687         torture_close_connection(cli1);
2688
2689         printf("finished locktest8\n");
2690         return correct;
2691 }
2692
2693 /*
2694  * This test is designed to be run in conjunction with
2695  * external NFS or POSIX locks taken in the filesystem.
2696  * It checks that the smbd server will block until the
2697  * lock is released and then acquire it. JRA.
2698  */
2699
2700 static bool got_alarm;
2701 static struct cli_state *alarm_cli;
2702
2703 static void alarm_handler(int dummy)
2704 {
2705         got_alarm = True;
2706 }
2707
2708 static void alarm_handler_parent(int dummy)
2709 {
2710         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2711 }
2712
2713 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2714 {
2715         int fd;
2716         char c = '\0';
2717         struct flock lock;
2718         const char *local_pathname = NULL;
2719         int ret;
2720
2721         local_pathname = talloc_asprintf(talloc_tos(),
2722                         "%s/%s", local_path, fname);
2723         if (!local_pathname) {
2724                 printf("child: alloc fail\n");
2725                 exit(1);
2726         }
2727
2728         unlink(local_pathname);
2729         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2730         if (fd == -1) {
2731                 printf("child: open of %s failed %s.\n",
2732                         local_pathname, strerror(errno));
2733                 exit(1);
2734         }
2735
2736         /* Now take a fcntl lock. */
2737         lock.l_type = F_WRLCK;
2738         lock.l_whence = SEEK_SET;
2739         lock.l_start = 0;
2740         lock.l_len = 4;
2741         lock.l_pid = getpid();
2742
2743         ret = fcntl(fd,F_SETLK,&lock);
2744         if (ret == -1) {
2745                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2746                         local_pathname, strerror(errno));
2747                 exit(1);
2748         } else {
2749                 printf("child: got lock 0:4 on file %s.\n",
2750                         local_pathname );
2751                 fflush(stdout);
2752         }
2753
2754         CatchSignal(SIGALRM, alarm_handler);
2755         alarm(5);
2756         /* Signal the parent. */
2757         if (write(write_fd, &c, 1) != 1) {
2758                 printf("child: start signal fail %s.\n",
2759                         strerror(errno));
2760                 exit(1);
2761         }
2762         alarm(0);
2763
2764         alarm(10);
2765         /* Wait for the parent to be ready. */
2766         if (read(read_fd, &c, 1) != 1) {
2767                 printf("child: reply signal fail %s.\n",
2768                         strerror(errno));
2769                 exit(1);
2770         }
2771         alarm(0);
2772
2773         sleep(5);
2774         close(fd);
2775         printf("child: released lock 0:4 on file %s.\n",
2776                 local_pathname );
2777         fflush(stdout);
2778         exit(0);
2779 }
2780
2781 static bool _run_locktest9X(const char *fname, int timeout)
2782 {
2783         struct cli_state *cli1;
2784         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2785         uint16_t fnum;
2786         bool correct = False;
2787         int pipe_in[2], pipe_out[2];
2788         pid_t child_pid;
2789         char c = '\0';
2790         int ret;
2791         struct timeval start;
2792         double seconds;
2793         NTSTATUS status;
2794
2795         printf("starting locktest9X: %s\n", fname);
2796
2797         if (local_path == NULL) {
2798                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2799                 return false;
2800         }
2801
2802         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2803                 return false;
2804         }
2805
2806         child_pid = fork();
2807         if (child_pid == -1) {
2808                 return false;
2809         }
2810
2811         if (child_pid == 0) {
2812                 /* Child. */
2813                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2814                 exit(0);
2815         }
2816
2817         close(pipe_out[0]);
2818         close(pipe_in[1]);
2819         pipe_out[0] = -1;
2820         pipe_in[1] = -1;
2821
2822         /* Parent. */
2823         ret = read(pipe_in[0], &c, 1);
2824         if (ret != 1) {
2825                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2826                         strerror(errno));
2827                 return false;
2828         }
2829
2830         if (!torture_open_connection(&cli1, 0)) {
2831                 return false;
2832         }
2833
2834         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2835
2836         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2837                           &fnum);
2838         if (!NT_STATUS_IS_OK(status)) {
2839                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2840                 return false;
2841         }
2842
2843         /* Ensure the child has the lock. */
2844         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2845         if (NT_STATUS_IS_OK(status)) {
2846                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2847                 goto fail;
2848         } else {
2849                 d_printf("Child has the lock.\n");
2850         }
2851
2852         /* Tell the child to wait 5 seconds then exit. */
2853         ret = write(pipe_out[1], &c, 1);
2854         if (ret != 1) {
2855                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2856                         strerror(errno));
2857                 goto fail;
2858         }
2859
2860         /* Wait 20 seconds for the lock. */
2861         alarm_cli = cli1;
2862         CatchSignal(SIGALRM, alarm_handler_parent);
2863         alarm(20);
2864
2865         start = timeval_current();
2866
2867         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2868         if (!NT_STATUS_IS_OK(status)) {
2869                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2870                        "%s\n", nt_errstr(status));
2871                 goto fail_nofd;
2872         }
2873         alarm(0);
2874
2875         seconds = timeval_elapsed(&start);
2876
2877         printf("Parent got the lock after %.2f seconds.\n",
2878                 seconds);
2879
2880         status = cli_close(cli1, fnum);
2881         if (!NT_STATUS_IS_OK(status)) {
2882                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2883                 goto fail;
2884         }
2885
2886         correct = true;
2887
2888 fail:
2889         cli_close(cli1, fnum);
2890         torture_close_connection(cli1);
2891
2892 fail_nofd:
2893
2894         printf("finished locktest9X: %s\n", fname);
2895         return correct;
2896 }
2897
2898 static bool run_locktest9a(int dummy)
2899 {
2900         return _run_locktest9X("lock9a.dat", -1);
2901 }
2902
2903 static bool run_locktest9b(int dummy)
2904 {
2905         return _run_locktest9X("lock9b.dat", 10000);
2906 }
2907
2908 struct locktest10_state {
2909         bool ok;
2910         bool done;
2911 };
2912
2913 static void locktest10_lockingx_done(struct tevent_req *subreq);
2914 static void locktest10_read_andx_done(struct tevent_req *subreq);
2915
2916 static bool run_locktest10(int dummy)
2917 {
2918         struct tevent_context *ev = NULL;
2919         struct cli_state *cli1 = NULL;
2920         struct cli_state *cli2 = NULL;
2921         struct smb1_lock_element lck = { 0 };
2922         struct tevent_req *reqs[2] = { NULL };
2923         struct tevent_req *smbreqs[2] = { NULL };
2924         const char fname[] = "\\lockt10.lck";
2925         uint16_t fnum1, fnum2;
2926         bool ret = false;
2927         bool ok;
2928         uint8_t data = 1;
2929         struct locktest10_state state = { .ok = true };
2930         NTSTATUS status;
2931
2932         printf("starting locktest10\n");
2933
2934         ev = samba_tevent_context_init(NULL);
2935         if (ev == NULL) {
2936                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2937                 goto done;
2938         }
2939
2940         ok = torture_open_connection(&cli1, 0);
2941         if (!ok) {
2942                 goto done;
2943         }
2944         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2945
2946         ok = torture_open_connection(&cli2, 1);
2947         if (!ok) {
2948                 goto done;
2949         }
2950         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2951
2952         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2953         if (!NT_STATUS_IS_OK(status)) {
2954                 d_fprintf(stderr,
2955                           "cli_openx failed: %s\n",
2956                           nt_errstr(status));
2957                 goto done;
2958         }
2959
2960         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2961         if (!NT_STATUS_IS_OK(status)) {
2962                 d_fprintf(stderr,
2963                           "cli_writeall failed: %s\n",
2964                           nt_errstr(status));
2965                 goto done;
2966         }
2967
2968         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2969         if (!NT_STATUS_IS_OK(status)) {
2970                 d_fprintf(stderr,
2971                           "cli_openx failed: %s\n",
2972                           nt_errstr(status));
2973                 goto done;
2974         }
2975
2976         status = cli_locktype(
2977                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2978         if (!NT_STATUS_IS_OK(status)) {
2979                 d_fprintf(stderr,
2980                           "cli_locktype failed: %s\n",
2981                           nt_errstr(status));
2982                 goto done;
2983         }
2984
2985         lck = (struct smb1_lock_element) {
2986                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2987         };
2988
2989         reqs[0] = cli_lockingx_create(
2990                 ev,                             /* mem_ctx */
2991                 ev,                             /* tevent_context */
2992                 cli1,                           /* cli */
2993                 fnum1,                          /* fnum */
2994                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2995                 0,                              /* newoplocklevel */
2996                 1,                              /* timeout */
2997                 0,                              /* num_unlocks */
2998                 NULL,                           /* unlocks */
2999                 1,                              /* num_locks */
3000                 &lck,                           /* locks */
3001                 &smbreqs[0]);                   /* psmbreq */
3002         if (reqs[0] == NULL) {
3003                 d_fprintf(stderr, "cli_lockingx_create failed\n");
3004                 goto done;
3005         }
3006         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3007
3008         reqs[1] = cli_read_andx_create(
3009                 ev,             /* mem_ctx */
3010                 ev,             /* ev */
3011                 cli1,           /* cli */
3012                 fnum1,          /* fnum */
3013                 0,              /* offset */
3014                 1,              /* size */
3015                 &smbreqs[1]);   /* psmbreq */
3016         if (reqs[1] == NULL) {
3017                 d_fprintf(stderr, "cli_read_andx_create failed\n");
3018                 goto done;
3019         }
3020         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3021
3022         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3023         if (!NT_STATUS_IS_OK(status)) {
3024                 d_fprintf(stderr,
3025                           "smb1cli_req_chain_submit failed: %s\n",
3026                           nt_errstr(status));
3027                 goto done;
3028         }
3029
3030         while (!state.done) {
3031                 tevent_loop_once(ev);
3032         }
3033
3034         torture_close_connection(cli1);
3035
3036         if (state.ok) {
3037                 ret = true;
3038         }
3039 done:
3040         return ret;
3041 }
3042
3043 static void locktest10_lockingx_done(struct tevent_req *subreq)
3044 {
3045         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3046         NTSTATUS status;
3047
3048         status = cli_lockingx_recv(subreq);
3049         TALLOC_FREE(subreq);
3050
3051         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3052                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3053                 state->ok = false;
3054         }
3055 }
3056
3057 static void locktest10_read_andx_done(struct tevent_req *subreq)
3058 {
3059         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3060         ssize_t received = -1;
3061         uint8_t *rcvbuf = NULL;
3062         NTSTATUS status;
3063
3064         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3065
3066         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3067                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3068                 state->ok = false;
3069         }
3070
3071         state->done = true;
3072         TALLOC_FREE(subreq);
3073 }
3074
3075 static bool run_locktest11(int dummy)
3076 {
3077         struct cli_state *cli1;
3078         const char *fname = "\\lockt11.lck";
3079         NTSTATUS status;
3080         uint16_t fnum;
3081         bool ret = false;
3082
3083         if (!torture_open_connection(&cli1, 0)) {
3084                 return false;
3085         }
3086
3087         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3088
3089         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3090
3091         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3092         if (!NT_STATUS_IS_OK(status)) {
3093                 d_fprintf(stderr,
3094                           "cli_openx returned %s\n",
3095                           nt_errstr(status));
3096                 return false;
3097         }
3098
3099         /*
3100          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3101          * returns NT_STATUS_OK
3102          */
3103
3104         status = cli_lockingx(
3105                 cli1,                           /* cli */
3106                 fnum,                           /* fnum */
3107                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3108                 0,                              /* newoplocklevel */
3109                 0,                              /* timeout */
3110                 0,                              /* num_unlocks */
3111                 NULL,                           /* unlocks */
3112                 0,                              /* num_locks */
3113                 NULL);                          /* locks */
3114
3115         if (!NT_STATUS_IS_OK(status)) {
3116                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3117                 goto fail;
3118         }
3119
3120         ret = true;
3121 fail:
3122         cli_close(cli1, fnum);
3123         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3124
3125         return ret;
3126 }
3127
3128 struct deferred_close_state {
3129         struct tevent_context *ev;
3130         struct cli_state *cli;
3131         uint16_t fnum;
3132 };
3133
3134 static void deferred_close_waited(struct tevent_req *subreq);
3135 static void deferred_close_done(struct tevent_req *subreq);
3136
3137 static struct tevent_req *deferred_close_send(
3138         TALLOC_CTX *mem_ctx,
3139         struct tevent_context *ev,
3140         int wait_secs,
3141         struct cli_state *cli,
3142         uint16_t fnum)
3143 {
3144         struct tevent_req *req = NULL, *subreq = NULL;
3145         struct deferred_close_state *state = NULL;
3146         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3147
3148         req = tevent_req_create(
3149                 mem_ctx, &state, struct deferred_close_state);
3150         if (req == NULL) {
3151                 return NULL;
3152         }
3153         state->ev = ev;
3154         state->cli = cli;
3155         state->fnum = fnum;
3156
3157         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3158         if (tevent_req_nomem(subreq, req)) {
3159                 return tevent_req_post(req, ev);
3160         }
3161         tevent_req_set_callback(subreq, deferred_close_waited, req);
3162         return req;
3163 }
3164
3165 static void deferred_close_waited(struct tevent_req *subreq)
3166 {
3167         struct tevent_req *req = tevent_req_callback_data(
3168                 subreq, struct tevent_req);
3169         struct deferred_close_state *state = tevent_req_data(
3170                 req, struct deferred_close_state);
3171         bool ok;
3172
3173         ok = tevent_wakeup_recv(subreq);
3174         TALLOC_FREE(subreq);
3175         if (!ok) {
3176                 tevent_req_oom(req);
3177                 return;
3178         }
3179
3180         subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3181         if (tevent_req_nomem(subreq, req)) {
3182                 return;
3183         }
3184         tevent_req_set_callback(subreq, deferred_close_done, req);
3185 }
3186
3187 static void deferred_close_done(struct tevent_req *subreq)
3188 {
3189         NTSTATUS status = cli_close_recv(subreq);
3190         tevent_req_simple_finish_ntstatus(subreq, status);
3191 }
3192
3193 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3194 {
3195         return tevent_req_simple_recv_ntstatus(req);
3196 }
3197
3198 struct lockread_state {
3199         struct smb1_lock_element lck;
3200         struct tevent_req *reqs[2];
3201         struct tevent_req *smbreqs[2];
3202         NTSTATUS lock_status;
3203         NTSTATUS read_status;
3204         uint8_t *readbuf;
3205 };
3206
3207 static void lockread_lockingx_done(struct tevent_req *subreq);
3208 static void lockread_read_andx_done(struct tevent_req *subreq);
3209
3210 static struct tevent_req *lockread_send(
3211         TALLOC_CTX *mem_ctx,
3212         struct tevent_context *ev,
3213         struct cli_state *cli,
3214         uint16_t fnum)
3215 {
3216         struct tevent_req *req = NULL;
3217         struct lockread_state *state = NULL;
3218         NTSTATUS status;
3219
3220         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3221         if (req == NULL) {
3222                 return NULL;
3223         }
3224
3225         state->lck = (struct smb1_lock_element) {
3226                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3227         };
3228
3229         state->reqs[0] = cli_lockingx_create(
3230                 ev,                             /* mem_ctx */
3231                 ev,                             /* tevent_context */
3232                 cli,                            /* cli */
3233                 fnum,                           /* fnum */
3234                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3235                 0,                              /* newoplocklevel */
3236                 10000,                          /* timeout */
3237                 0,                              /* num_unlocks */
3238                 NULL,                           /* unlocks */
3239                 1,                              /* num_locks */
3240                 &state->lck,                    /* locks */
3241                 &state->smbreqs[0]);            /* psmbreq */
3242         if (tevent_req_nomem(state->reqs[0], req)) {
3243                 return tevent_req_post(req, ev);
3244         }
3245         tevent_req_set_callback(
3246                 state->reqs[0], lockread_lockingx_done, req);
3247
3248         state->reqs[1] = cli_read_andx_create(
3249                 ev,             /* mem_ctx */
3250                 ev,             /* ev */
3251                 cli,            /* cli */
3252                 fnum,           /* fnum */
3253                 0,              /* offset */
3254                 1,              /* size */
3255                 &state->smbreqs[1]);    /* psmbreq */
3256         if (tevent_req_nomem(state->reqs[1], req)) {
3257                 return tevent_req_post(req, ev);
3258         }
3259         tevent_req_set_callback(
3260                 state->reqs[1], lockread_read_andx_done, req);
3261
3262         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3263         if (tevent_req_nterror(req, status)) {
3264                 return tevent_req_post(req, ev);
3265         }
3266         return req;
3267 }
3268
3269 static void lockread_lockingx_done(struct tevent_req *subreq)
3270 {
3271         struct tevent_req *req = tevent_req_callback_data(
3272                 subreq, struct tevent_req);
3273         struct lockread_state *state = tevent_req_data(
3274                 req, struct lockread_state);
3275         state->lock_status = cli_lockingx_recv(subreq);
3276         TALLOC_FREE(subreq);
3277         d_fprintf(stderr,
3278                   "lockingx returned %s\n",
3279                   nt_errstr(state->lock_status));
3280 }
3281
3282 static void lockread_read_andx_done(struct tevent_req *subreq)
3283 {
3284         struct tevent_req *req = tevent_req_callback_data(
3285                 subreq, struct tevent_req);
3286         struct lockread_state *state = tevent_req_data(
3287                 req, struct lockread_state);
3288         ssize_t received = -1;
3289         uint8_t *rcvbuf = NULL;
3290
3291         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3292
3293         d_fprintf(stderr,
3294                   "read returned %s\n",
3295                   nt_errstr(state->read_status));
3296
3297         if (!NT_STATUS_IS_OK(state->read_status)) {
3298                 TALLOC_FREE(subreq);
3299                 tevent_req_done(req);
3300                 return;
3301         }
3302
3303         if (received > 0) {
3304                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3305                 TALLOC_FREE(subreq);
3306                 if (tevent_req_nomem(state->readbuf, req)) {
3307                         return;
3308                 }
3309         }
3310         TALLOC_FREE(subreq);
3311         tevent_req_done(req);
3312 }
3313
3314 static NTSTATUS lockread_recv(
3315         struct tevent_req *req,
3316         NTSTATUS *lock_status,
3317         NTSTATUS *read_status,
3318         TALLOC_CTX *mem_ctx,
3319         uint8_t **read_buf)
3320 {
3321         struct lockread_state *state = tevent_req_data(
3322                 req, struct lockread_state);
3323         NTSTATUS status;
3324
3325         if (tevent_req_is_nterror(req, &status)) {
3326                 return status;
3327         }
3328
3329         *lock_status = state->lock_status;
3330         *read_status = state->read_status;
3331         if (state->readbuf != NULL) {
3332                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3333         } else {
3334                 *read_buf = NULL;
3335         }
3336
3337         return NT_STATUS_OK;
3338 }
3339
3340 struct lock12_state {
3341         uint8_t dummy;
3342 };
3343
3344 static void lock12_closed(struct tevent_req *subreq);
3345 static void lock12_read(struct tevent_req *subreq);
3346
3347 static struct tevent_req *lock12_send(
3348         TALLOC_CTX *mem_ctx,
3349         struct tevent_context *ev,
3350         struct cli_state *cli,
3351         uint16_t fnum1,
3352         uint16_t fnum2)
3353 {
3354         struct tevent_req *req = NULL, *subreq = NULL;
3355         struct lock12_state *state = NULL;
3356
3357         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3358         if (req == NULL) {
3359                 return NULL;
3360         }
3361
3362         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3363         if (tevent_req_nomem(subreq, req)) {
3364                 return tevent_req_post(req, ev);
3365         }
3366         tevent_req_set_callback(subreq, lock12_closed, req);
3367
3368         subreq = lockread_send(state, ev, cli, fnum2);
3369         if (tevent_req_nomem(subreq, req)) {
3370                 return tevent_req_post(req, ev);
3371         }
3372         tevent_req_set_callback(subreq, lock12_read, req);
3373
3374         return req;
3375 }
3376
3377 static void lock12_closed(struct tevent_req *subreq)
3378 {
3379         struct tevent_req *req = tevent_req_callback_data(
3380                 subreq, struct tevent_req);
3381         NTSTATUS status;
3382
3383         status = deferred_close_recv(subreq);
3384         TALLOC_FREE(subreq);
3385         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3386         if (tevent_req_nterror(req, status)) {
3387                 return;
3388         }
3389 }
3390
3391 static void lock12_read(struct tevent_req *subreq)
3392 {
3393         struct tevent_req *req = tevent_req_callback_data(
3394                 subreq, struct tevent_req);
3395         struct lock12_state *state = tevent_req_data(
3396                 req, struct lock12_state);
3397         NTSTATUS status, lock_status, read_status;
3398         uint8_t *buf = NULL;
3399
3400         status = lockread_recv(
3401                 subreq, &lock_status, &read_status, state, &buf);
3402         TALLOC_FREE(subreq);
3403         if (tevent_req_nterror(req, status) ||
3404             tevent_req_nterror(req, lock_status) ||
3405             tevent_req_nterror(req, read_status)) {
3406                 return;
3407         }
3408         tevent_req_done(req);
3409 }
3410
3411 static NTSTATUS lock12_recv(struct tevent_req *req)
3412
3413 {
3414         NTSTATUS status;
3415
3416         if (tevent_req_is_nterror(req, &status)) {
3417                 return status;
3418         }
3419         return NT_STATUS_OK;
3420 }
3421
3422 static bool run_locktest12(int dummy)
3423 {
3424         struct tevent_context *ev = NULL;
3425         struct tevent_req *req = NULL;
3426         struct cli_state *cli = NULL;
3427         const char fname[] = "\\lockt12.lck";
3428         uint16_t fnum1, fnum2;
3429         bool ret = false;
3430         bool ok;
3431         uint8_t data = 1;
3432         NTSTATUS status;
3433
3434         printf("starting locktest12\n");
3435
3436         ev = samba_tevent_context_init(NULL);
3437         if (ev == NULL) {
3438                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3439                 goto done;
3440         }
3441
3442         ok = torture_open_connection(&cli, 0);
3443         if (!ok) {
3444                 goto done;
3445         }
3446         smbXcli_conn_set_sockopt(cli->conn, sockops);
3447
3448         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3449         if (!NT_STATUS_IS_OK(status)) {
3450                 d_fprintf(stderr,
3451                           "cli_openx failed: %s\n",
3452                           nt_errstr(status));
3453                 goto done;
3454         }
3455
3456         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3457         if (!NT_STATUS_IS_OK(status)) {
3458                 d_fprintf(stderr,
3459                           "cli_openx failed: %s\n",
3460                           nt_errstr(status));
3461                 goto done;
3462         }
3463
3464         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3465         if (!NT_STATUS_IS_OK(status)) {
3466                 d_fprintf(stderr,
3467                           "cli_writeall failed: %s\n",
3468                           nt_errstr(status));
3469                 goto done;
3470         }
3471
3472         status = cli_locktype(
3473                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3474         if (!NT_STATUS_IS_OK(status)) {
3475                 d_fprintf(stderr,
3476                           "cli_locktype failed: %s\n",
3477                           nt_errstr(status));
3478                 goto done;
3479         }
3480
3481         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3482         if (req == NULL) {
3483                 d_fprintf(stderr, "lock12_send failed\n");
3484                 goto done;
3485         }
3486
3487         ok = tevent_req_poll_ntstatus(req, ev, &status);
3488         if (!ok) {
3489                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3490                 goto done;
3491         }
3492
3493         if (!NT_STATUS_IS_OK(status)) {
3494                 d_fprintf(stderr,
3495                           "tevent_req_poll_ntstatus returned %s\n",
3496                           nt_errstr(status));
3497                 goto done;
3498         }
3499
3500         status = lock12_recv(req);
3501         if (!NT_STATUS_IS_OK(status)) {
3502                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3503                 goto done;
3504         }
3505
3506         ret = true;
3507 done:
3508         if (cli != NULL) {
3509                 torture_close_connection(cli);
3510         }
3511         return ret;
3512 }
3513
3514 struct lock_ntcancel_state {
3515         struct timeval start;
3516         struct smb1_lock_element lck;
3517         struct tevent_req *subreq;
3518 };
3519
3520 static void lock_ntcancel_waited(struct tevent_req *subreq);
3521 static void lock_ntcancel_done(struct tevent_req *subreq);
3522
3523 static struct tevent_req *lock_ntcancel_send(
3524         TALLOC_CTX *mem_ctx,
3525         struct tevent_context *ev,
3526         struct cli_state *cli,
3527         uint16_t fnum)
3528 {
3529         struct tevent_req *req = NULL, *subreq = NULL;
3530         struct lock_ntcancel_state *state = NULL;
3531
3532         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3533         if (req == NULL) {
3534                 return NULL;
3535         }
3536         state->lck = (struct smb1_lock_element) {
3537                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3538         };
3539         state->start = timeval_current();
3540
3541         state->subreq = cli_lockingx_send(
3542                 state,                          /* mem_ctx */
3543                 ev,                             /* tevent_context */
3544                 cli,                            /* cli */
3545                 fnum,                           /* fnum */
3546                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3547                 0,                              /* newoplocklevel */
3548                 10000,                          /* timeout */
3549                 0,                              /* num_unlocks */
3550                 NULL,                           /* unlocks */
3551                 1,                              /* num_locks */
3552                 &state->lck);                   /* locks */
3553         if (tevent_req_nomem(state->subreq, req)) {
3554                 return tevent_req_post(req, ev);
3555         }
3556         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3557
3558         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3559         if (tevent_req_nomem(subreq, req)) {
3560                 return tevent_req_post(req, ev);
3561         }
3562         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3563         return req;
3564 }
3565
3566 static void lock_ntcancel_waited(struct tevent_req *subreq)
3567 {
3568         struct tevent_req *req = tevent_req_callback_data(
3569                 subreq, struct tevent_req);
3570         struct lock_ntcancel_state *state = tevent_req_data(
3571                 req, struct lock_ntcancel_state);
3572         bool ok;
3573
3574         ok = tevent_wakeup_recv(subreq);
3575         TALLOC_FREE(subreq);
3576         if (!ok) {
3577                 tevent_req_oom(req);
3578                 return;
3579         }
3580
3581         ok = tevent_req_cancel(state->subreq);
3582         if (!ok) {
3583                 d_fprintf(stderr, "Could not cancel subreq\n");
3584                 tevent_req_oom(req);
3585                 return;
3586         }
3587 }
3588
3589 static void lock_ntcancel_done(struct tevent_req *subreq)
3590 {
3591         struct tevent_req *req = tevent_req_callback_data(
3592                 subreq, struct tevent_req);
3593         struct lock_ntcancel_state *state = tevent_req_data(
3594                 req, struct lock_ntcancel_state);
3595         NTSTATUS status;
3596         double elapsed;
3597
3598         status = cli_lockingx_recv(subreq);
3599         TALLOC_FREE(subreq);
3600
3601         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3602                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3603                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3604                 return;
3605         }
3606
3607         elapsed = timeval_elapsed(&state->start);
3608
3609         if (elapsed > 3) {
3610                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3611                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3612                 return;
3613         }
3614
3615         tevent_req_done(req);
3616 }
3617
3618 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3619 {
3620         return tevent_req_simple_recv_ntstatus(req);
3621 }
3622
3623 static bool run_locktest13(int dummy)
3624 {
3625         struct tevent_context *ev = NULL;
3626         struct tevent_req *req = NULL;
3627         struct cli_state *cli = NULL;
3628         const char fname[] = "\\lockt13.lck";
3629         uint16_t fnum1, fnum2;
3630         bool ret = false;
3631         bool ok;
3632         uint8_t data = 1;
3633         NTSTATUS status;
3634
3635         printf("starting locktest13\n");
3636
3637         ev = samba_tevent_context_init(NULL);
3638         if (ev == NULL) {
3639                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3640                 goto done;
3641         }
3642
3643         ok = torture_open_connection(&cli, 0);
3644         if (!ok) {
3645                 goto done;
3646         }
3647         smbXcli_conn_set_sockopt(cli->conn, sockops);
3648
3649         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3650         if (!NT_STATUS_IS_OK(status)) {
3651                 d_fprintf(stderr,
3652                           "cli_openx failed: %s\n",
3653                           nt_errstr(status));
3654                 goto done;
3655         }
3656
3657         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3658         if (!NT_STATUS_IS_OK(status)) {
3659                 d_fprintf(stderr,
3660                           "cli_openx failed: %s\n",
3661                           nt_errstr(status));
3662                 goto done;
3663         }
3664
3665         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3666         if (!NT_STATUS_IS_OK(status)) {
3667                 d_fprintf(stderr,
3668                           "cli_writeall failed: %s\n",
3669                           nt_errstr(status));
3670                 goto done;
3671         }
3672
3673         status = cli_locktype(
3674                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3675         if (!NT_STATUS_IS_OK(status)) {
3676                 d_fprintf(stderr,
3677                           "cli_locktype failed: %s\n",
3678                           nt_errstr(status));
3679                 goto done;
3680         }
3681
3682         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3683         if (req == NULL) {
3684                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3685                 goto done;
3686         }
3687
3688         ok = tevent_req_poll_ntstatus(req, ev, &status);
3689         if (!ok) {
3690                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3691                 goto done;
3692         }
3693
3694         if (!NT_STATUS_IS_OK(status)) {
3695                 d_fprintf(stderr,
3696                           "tevent_req_poll_ntstatus returned %s\n",
3697                           nt_errstr(status));
3698                 goto done;
3699         }
3700
3701         status = lock_ntcancel_recv(req);
3702         if (!NT_STATUS_IS_OK(status)) {
3703                 d_fprintf(stderr,
3704                           "lock_ntcancel returned %s\n",
3705                           nt_errstr(status));
3706                 goto done;
3707         }
3708
3709         ret = true;
3710 done:
3711         if (cli != NULL) {
3712                 torture_close_connection(cli);
3713         }
3714         return ret;
3715 }
3716
3717 /*
3718 test whether fnums and tids open on one VC are available on another (a major
3719 security hole)
3720 */
3721 static bool run_fdpasstest(int dummy)
3722 {
3723         struct cli_state *cli1, *cli2;
3724         const char *fname = "\\fdpass.tst";
3725         uint16_t fnum1;
3726         char buf[1024];
3727         NTSTATUS status;
3728
3729         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3730                 return False;
3731         }
3732         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3733         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3734
3735         printf("starting fdpasstest\n");
3736
3737         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3738
3739         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3740                           &fnum1);
3741         if (!NT_STATUS_IS_OK(status)) {
3742                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3743                 return False;
3744         }
3745
3746         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3747                               13, NULL);
3748         if (!NT_STATUS_IS_OK(status)) {
3749                 printf("write failed (%s)\n", nt_errstr(status));
3750                 return False;
3751         }
3752
3753         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3754         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3755         cli_setpid(cli2, cli_getpid(cli1));
3756
3757         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3758                 printf("read succeeded! nasty security hole [%s]\n", buf);
3759                 return false;
3760         }
3761
3762         cli_close(cli1, fnum1);
3763         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3764
3765         torture_close_connection(cli1);
3766         torture_close_connection(cli2);
3767
3768         printf("finished fdpasstest\n");
3769         return True;
3770 }
3771
3772 static bool run_fdsesstest(int dummy)
3773 {
3774         struct cli_state *cli;
3775         uint16_t new_vuid;
3776         uint16_t saved_vuid;
3777         uint32_t new_cnum;
3778         uint32_t saved_cnum;
3779         const char *fname = "\\fdsess.tst";
3780         const char *fname1 = "\\fdsess1.tst";
3781         uint16_t fnum1;
3782         uint16_t fnum2;
3783         char buf[1024];
3784         bool ret = True;
3785         NTSTATUS status;
3786
3787         if (!torture_open_connection(&cli, 0))
3788                 return False;
3789         smbXcli_conn_set_sockopt(cli->conn, sockops);
3790
3791         if (!torture_cli_session_setup2(cli, &new_vuid))
3792                 return False;
3793
3794         saved_cnum = cli_state_get_tid(cli);
3795         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3796                 return False;
3797         new_cnum = cli_state_get_tid(cli);
3798         cli_state_set_tid(cli, saved_cnum);
3799
3800         printf("starting fdsesstest\n");
3801
3802         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3803         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804
3805         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3806         if (!NT_STATUS_IS_OK(status)) {
3807                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3808                 return False;
3809         }
3810
3811         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3812                               NULL);
3813         if (!NT_STATUS_IS_OK(status)) {
3814                 printf("write failed (%s)\n", nt_errstr(status));
3815                 return False;
3816         }
3817
3818         saved_vuid = cli_state_get_uid(cli);
3819         cli_state_set_uid(cli, new_vuid);
3820
3821         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3822                 printf("read succeeded with different vuid! "
3823                        "nasty security hole [%s]\n", buf);
3824                 ret = false;
3825         }
3826         /* Try to open a file with different vuid, samba cnum. */
3827         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3828                 printf("create with different vuid, same cnum succeeded.\n");
3829                 cli_close(cli, fnum2);
3830                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3831         } else {
3832                 printf("create with different vuid, same cnum failed.\n");
3833                 printf("This will cause problems with service clients.\n");
3834                 ret = False;
3835         }
3836
3837         cli_state_set_uid(cli, saved_vuid);
3838
3839         /* Try with same vuid, different cnum. */
3840         cli_state_set_tid(cli, new_cnum);
3841
3842         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3843                 printf("read succeeded with different cnum![%s]\n", buf);
3844                 ret = false;
3845         }
3846
3847         cli_state_set_tid(cli, saved_cnum);
3848         cli_close(cli, fnum1);
3849         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3850
3851         torture_close_connection(cli);
3852
3853         printf("finished fdsesstest\n");
3854         return ret;
3855 }
3856
3857 /*
3858   This test checks that 
3859
3860   1) the server does not allow an unlink on a file that is open
3861 */
3862 static bool run_unlinktest(int dummy)
3863 {
3864         struct cli_state *cli;
3865         const char *fname = "\\unlink.tst";
3866         uint16_t fnum;
3867         bool correct = True;
3868         NTSTATUS status;
3869
3870         if (!torture_open_connection(&cli, 0)) {
3871                 return False;
3872         }
3873
3874         smbXcli_conn_set_sockopt(cli->conn, sockops);
3875
3876         printf("starting unlink test\n");
3877
3878         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3879
3880         cli_setpid(cli, 1);
3881
3882         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3883         if (!NT_STATUS_IS_OK(status)) {
3884                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3885                 return False;
3886         }
3887
3888         status = cli_unlink(cli, fname,
3889                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3890         if (NT_STATUS_IS_OK(status)) {
3891                 printf("error: server allowed unlink on an open file\n");
3892                 correct = False;
3893         } else {
3894                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3895                                       NT_STATUS_SHARING_VIOLATION);
3896         }
3897
3898         cli_close(cli, fnum);
3899         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3900
3901         if (!torture_close_connection(cli)) {
3902                 correct = False;
3903         }
3904
3905         printf("unlink test finished\n");
3906
3907         return correct;
3908 }
3909
3910
3911 /*
3912 test how many open files this server supports on the one socket
3913 */
3914 static bool run_maxfidtest(int dummy)
3915 {
3916         struct cli_state *cli;
3917         fstring fname;
3918         uint16_t fnums[0x11000];
3919         int i;
3920         int retries=4;
3921         bool correct = True;
3922         NTSTATUS status;
3923
3924         cli = current_cli;
3925
3926         if (retries <= 0) {
3927                 printf("failed to connect\n");
3928                 return False;
3929         }
3930
3931         smbXcli_conn_set_sockopt(cli->conn, sockops);
3932
3933         for (i=0; i<0x11000; i++) {
3934                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3935                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3936                                   &fnums[i]);
3937                 if (!NT_STATUS_IS_OK(status)) {
3938                         printf("open of %s failed (%s)\n", 
3939                                fname, nt_errstr(status));
3940                         printf("maximum fnum is %d\n", i);
3941                         break;
3942                 }
3943                 printf("%6d\r", i);
3944         }
3945         printf("%6d\n", i);
3946         i--;
3947
3948         printf("cleaning up\n");
3949         for (;i>=0;i--) {
3950                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3951                 cli_close(cli, fnums[i]);
3952
3953                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954                 if (!NT_STATUS_IS_OK(status)) {
3955                         printf("unlink of %s failed (%s)\n", 
3956                                fname, nt_errstr(status));
3957                         correct = False;
3958                 }
3959                 printf("%6d\r", i);
3960         }
3961         printf("%6d\n", 0);
3962
3963         printf("maxfid test finished\n");
3964         if (!torture_close_connection(cli)) {
3965                 correct = False;
3966         }
3967         return correct;
3968 }
3969
3970 /* generate a random buffer */
3971 static void rand_buf(char *buf, int len)
3972 {
3973         while (len--) {
3974                 *buf = (char)sys_random();
3975                 buf++;
3976         }
3977 }
3978
3979 /* send smb negprot commands, not reading the response */
3980 static bool run_negprot_nowait(int dummy)
3981 {
3982         struct tevent_context *ev;
3983         int i;
3984         struct cli_state *cli;
3985         bool correct = True;
3986
3987         printf("starting negprot nowait test\n");
3988
3989         ev = samba_tevent_context_init(talloc_tos());
3990         if (ev == NULL) {
3991                 return false;
3992         }
3993
3994         if (!(cli = open_nbt_connection())) {
3995                 TALLOC_FREE(ev);
3996                 return False;
3997         }
3998
3999         for (i=0;i<50000;i++) {
4000                 struct tevent_req *req;
4001
4002                 req = smbXcli_negprot_send(
4003                         ev,
4004                         ev,
4005                         cli->conn,
4006                         cli->timeout,
4007                         PROTOCOL_CORE,
4008                         PROTOCOL_NT1,
4009                         0,
4010                         NULL);
4011                 if (req == NULL) {
4012                         TALLOC_FREE(ev);
4013                         return false;
4014                 }
4015                 if (!tevent_req_poll(req, ev)) {
4016                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4017                                   strerror(errno));
4018                         TALLOC_FREE(ev);
4019                         return false;
4020                 }
4021                 TALLOC_FREE(req);
4022         }
4023
4024         if (torture_close_connection(cli)) {
4025                 correct = False;
4026         }
4027
4028         printf("finished negprot nowait test\n");
4029
4030         return correct;
4031 }
4032
4033 /* send smb negprot commands, not reading the response */
4034 static bool run_bad_nbt_session(int dummy)
4035 {
4036         struct nmb_name called, calling;
4037         struct sockaddr_storage ss;
4038         NTSTATUS status;
4039         int fd;
4040         bool ret;
4041
4042         printf("starting bad nbt session test\n");
4043
4044         make_nmb_name(&calling, myname, 0x0);
4045         make_nmb_name(&called , host, 0x20);
4046
4047         if (!resolve_name(host, &ss, 0x20, true)) {
4048                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4049                 return false;
4050         }
4051
4052         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4053         if (!NT_STATUS_IS_OK(status)) {
4054                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4055                           nt_errstr(status));
4056                 return false;
4057         }
4058
4059         ret = cli_bad_session_request(fd, &calling, &called);
4060         close(fd);
4061         if (!ret) {
4062                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4063                           nt_errstr(status));
4064                 return false;
4065         }
4066
4067         printf("finished bad nbt session test\n");
4068         return true;
4069 }
4070
4071 /* send random IPC commands */
4072 static bool run_randomipc(int dummy)
4073 {
4074         char *rparam = NULL;
4075         char *rdata = NULL;
4076         unsigned int rdrcnt,rprcnt;
4077         char param[1024];
4078         int api, param_len, i;
4079         struct cli_state *cli;
4080         bool correct = True;
4081         int count = 50000;
4082
4083         printf("starting random ipc test\n");
4084
4085         if (!torture_open_connection(&cli, 0)) {
4086                 return False;
4087         }
4088
4089         for (i=0;i<count;i++) {
4090                 api = sys_random() % 500;
4091                 param_len = (sys_random() % 64);
4092
4093                 rand_buf(param, param_len);
4094
4095                 SSVAL(param,0,api); 
4096
4097                 cli_api(cli, 
4098                         param, param_len, 8,  
4099                         NULL, 0, CLI_BUFFER_SIZE,
4100                         &rparam, &rprcnt,     
4101                         &rdata, &rdrcnt);
4102                 if (i % 100 == 0) {
4103                         printf("%d/%d\r", i,count);
4104                 }
4105         }
4106         printf("%d/%d\n", i, count);
4107
4108         if (!torture_close_connection(cli)) {
4109                 correct = False;
4110         }
4111
4112         SAFE_FREE(rparam);
4113         SAFE_FREE(rdata);
4114
4115         printf("finished random ipc test\n");
4116
4117         return correct;
4118 }
4119
4120
4121
4122 static void browse_callback(const char *sname, uint32_t stype,
4123                             const char *comment, void *state)
4124 {
4125         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4126 }
4127
4128
4129
4130 /*
4131   This test checks the browse list code
4132
4133 */
4134 static bool run_browsetest(int dummy)
4135 {
4136         static struct cli_state *cli;
4137         bool correct = True;
4138
4139         printf("starting browse test\n");
4140
4141         if (!torture_open_connection(&cli, 0)) {
4142                 return False;
4143         }
4144
4145         printf("domain list:\n");
4146         cli_NetServerEnum(cli, cli->server_domain, 
4147                           SV_TYPE_DOMAIN_ENUM,
4148                           browse_callback, NULL);
4149
4150         printf("machine list:\n");
4151         cli_NetServerEnum(cli, cli->server_domain, 
4152                           SV_TYPE_ALL,
4153                           browse_callback, NULL);
4154
4155         if (!torture_close_connection(cli)) {
4156                 correct = False;
4157         }
4158
4159         printf("browse test finished\n");
4160
4161         return correct;
4162
4163 }
4164
4165 static bool check_attributes(struct cli_state *cli,
4166                                 const char *fname,
4167                                 uint32_t expected_attrs)
4168 {
4169         uint32_t attrs = 0;
4170         NTSTATUS status = cli_getatr(cli,
4171                                 fname,
4172                                 &attrs,
4173                                 NULL,
4174                                 NULL);
4175         if (!NT_STATUS_IS_OK(status)) {
4176                 printf("cli_getatr failed with %s\n",
4177                         nt_errstr(status));
4178                 return false;
4179         }
4180         if (attrs != expected_attrs) {
4181                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4182                         (unsigned int)attrs,
4183                         (unsigned int)expected_attrs);
4184                 return false;
4185         }
4186         return true;
4187 }
4188
4189 /*
4190   This checks how the getatr calls works
4191 */
4192 static bool run_attrtest(int dummy)
4193 {
4194         struct cli_state *cli;
4195         uint16_t fnum;
4196         time_t t, t2;
4197         const char *fname = "\\attrib123456789.tst";
4198         bool correct = True;
4199         NTSTATUS status;
4200
4201         printf("starting attrib test\n");
4202
4203         if (!torture_open_connection(&cli, 0)) {
4204                 return False;
4205         }
4206
4207         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4208         status = cli_unlink(cli, fname, 0x20000);
4209         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4210                 correct = false;
4211                 goto out;
4212         }
4213
4214         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4215         cli_openx(cli, fname, 
4216                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4217         cli_close(cli, fnum);
4218
4219         status = cli_getatr(cli, fname, NULL, NULL, &t);
4220         if (!NT_STATUS_IS_OK(status)) {
4221                 printf("getatr failed (%s)\n", nt_errstr(status));
4222                 correct = False;
4223         }
4224
4225         if (labs(t - time(NULL)) > 60*60*24*10) {
4226                 printf("ERROR: SMBgetatr bug. time is %s",
4227                        ctime(&t));
4228                 t = time(NULL);
4229                 correct = True;
4230         }
4231
4232         t2 = t-60*60*24; /* 1 day ago */
4233
4234         /* Ensure we can't set with out-of-range (unknown) attribute. */
4235         status = cli_setatr(cli, fname, 0x20000, t2);
4236         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4237                 correct = false;
4238                 goto out;
4239         }
4240
4241         status = cli_setatr(cli, fname, 0, t2);
4242         if (!NT_STATUS_IS_OK(status)) {
4243                 printf("setatr failed (%s)\n", nt_errstr(status));
4244                 correct = True;
4245         }
4246
4247         status = cli_getatr(cli, fname, NULL, NULL, &t);
4248         if (!NT_STATUS_IS_OK(status)) {
4249                 printf("getatr failed (%s)\n", nt_errstr(status));
4250                 correct = True;
4251         }
4252
4253         if (t != t2) {
4254                 printf("ERROR: getatr/setatr bug. times are\n%s",
4255                        ctime(&t));
4256                 printf("%s", ctime(&t2));
4257                 correct = True;
4258         }
4259
4260         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4261
4262         /* Check cli_setpathinfo_ext() */
4263         /* Re-create the file. */
4264         status = cli_openx(cli, fname,
4265                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4266         if (!NT_STATUS_IS_OK(status)) {
4267                 printf("Failed to recreate %s (%s)\n",
4268                         fname, nt_errstr(status));
4269                 correct = false;
4270         }
4271         cli_close(cli, fnum);
4272
4273         status = cli_setpathinfo_ext(
4274                 cli,
4275                 fname,
4276                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4277                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4278                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4279                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4280                 FILE_ATTRIBUTE_SYSTEM |
4281                 FILE_ATTRIBUTE_HIDDEN |
4282                 FILE_ATTRIBUTE_READONLY);
4283         if (!NT_STATUS_IS_OK(status)) {
4284                 printf("cli_setpathinfo_ext failed with %s\n",
4285                         nt_errstr(status));
4286                 correct = false;
4287         }
4288
4289         /* Check attributes are correct. */
4290         correct = check_attributes(cli,
4291                         fname,
4292                         FILE_ATTRIBUTE_SYSTEM |
4293                         FILE_ATTRIBUTE_HIDDEN |
4294                         FILE_ATTRIBUTE_READONLY);
4295         if (correct == false) {
4296                 goto out;
4297         }
4298
4299         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4300         status = cli_setpathinfo_ext(
4301                 cli,
4302                 fname,
4303                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4304                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4305                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4306                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4307                 FILE_ATTRIBUTE_NORMAL);
4308         if (!NT_STATUS_IS_OK(status)) {
4309                 printf("cli_setpathinfo_ext failed with %s\n",
4310                         nt_errstr(status));
4311                 correct = false;
4312         }
4313
4314         /* Check attributes are correct. */
4315         correct = check_attributes(cli,
4316                         fname,
4317                         FILE_ATTRIBUTE_SYSTEM |
4318                         FILE_ATTRIBUTE_HIDDEN |
4319                         FILE_ATTRIBUTE_READONLY);
4320         if (correct == false) {
4321                 goto out;
4322         }
4323
4324         /* Setting to (uint16_t)-1 should also be ignored. */
4325         status = cli_setpathinfo_ext(
4326                 cli,
4327                 fname,
4328                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4329                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4330                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4331                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4332                 (uint32_t)-1);
4333         if (!NT_STATUS_IS_OK(status)) {
4334                 printf("cli_setpathinfo_ext failed with %s\n",
4335                         nt_errstr(status));
4336                 correct = false;
4337         }
4338
4339         /* Check attributes are correct. */
4340         correct = check_attributes(cli,
4341                         fname,
4342                         FILE_ATTRIBUTE_SYSTEM |
4343                         FILE_ATTRIBUTE_HIDDEN |
4344                         FILE_ATTRIBUTE_READONLY);
4345         if (correct == false) {
4346                 goto out;
4347         }
4348
4349         /* Setting to 0 should clear them all. */
4350         status = cli_setpathinfo_ext(
4351                 cli,
4352                 fname,
4353                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4354                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4355                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4356                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4357                 0);
4358         if (!NT_STATUS_IS_OK(status)) {
4359                 printf("cli_setpathinfo_ext failed with %s\n",
4360                         nt_errstr(status));
4361                 correct = false;
4362         }
4363
4364         /* Check attributes are correct. */
4365         correct = check_attributes(cli,
4366                         fname,
4367                         FILE_ATTRIBUTE_NORMAL);
4368         if (correct == false) {
4369                 goto out;
4370         }
4371
4372   out:
4373
4374         cli_unlink(cli,
4375                 fname,
4376                 FILE_ATTRIBUTE_SYSTEM |
4377                 FILE_ATTRIBUTE_HIDDEN|
4378                 FILE_ATTRIBUTE_READONLY);
4379
4380         if (!torture_close_connection(cli)) {
4381                 correct = False;
4382         }
4383
4384         printf("attrib test finished\n");
4385
4386         return correct;
4387 }
4388
4389 static NTSTATUS cli_qfilename(
4390         struct cli_state *cli,
4391         uint16_t fnum,
4392         TALLOC_CTX *mem_ctx,
4393         char **_name)
4394 {
4395         uint16_t recv_flags2;
4396         uint8_t *rdata;
4397         uint32_t num_rdata;
4398         NTSTATUS status;
4399         char *name = NULL;
4400         uint32_t namelen;
4401
4402         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4403                                SMB_QUERY_FILE_NAME_INFO,
4404                                4, CLI_BUFFER_SIZE, &recv_flags2,
4405                                &rdata, &num_rdata);
4406         if (!NT_STATUS_IS_OK(status)) {
4407                 return status;
4408         }
4409
4410         namelen = IVAL(rdata, 0);
4411         if (namelen > (num_rdata - 4)) {
4412                 TALLOC_FREE(rdata);
4413                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4414         }
4415
4416         pull_string_talloc(mem_ctx,
4417                            (const char *)rdata,
4418                            recv_flags2,
4419                            &name,
4420                            rdata + 4,
4421                            namelen,
4422                            STR_UNICODE);
4423         if (name == NULL) {
4424                 status = map_nt_error_from_unix(errno);
4425                 TALLOC_FREE(rdata);
4426                 return status;
4427         }
4428
4429         *_name = name;
4430         TALLOC_FREE(rdata);
4431         return NT_STATUS_OK;
4432 }
4433
4434 /*
4435   This checks a couple of trans2 calls
4436 */
4437 static bool run_trans2test(int dummy)
4438 {
4439         struct cli_state *cli;
4440         uint16_t fnum;
4441         off_t size;
4442         time_t c_time, a_time, m_time;
4443         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4444         const char *fname = "\\trans2.tst";
4445         const char *dname = "\\trans2";
4446         const char *fname2 = "\\trans2\\trans2.tst";
4447         char *pname = NULL;
4448         bool correct = True;
4449         NTSTATUS status;
4450         uint32_t fs_attr;
4451         uint64_t ino;
4452
4453         printf("starting trans2 test\n");
4454
4455         if (!torture_open_connection(&cli, 0)) {
4456                 return False;
4457         }
4458
4459         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4460                 /* Ensure ino is zero, SMB2 gets a real one. */
4461                 ino = 0;
4462         } else {
4463                 /* Ensure ino is -1, SMB1 never gets a real one. */
4464                 ino = (uint64_t)-1;
4465         }
4466
4467         status = cli_get_fs_attr_info(cli, &fs_attr);
4468         if (!NT_STATUS_IS_OK(status)) {
4469                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4470                        nt_errstr(status));
4471                 correct = false;
4472         }
4473
4474         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4476         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4477                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4478         if (!NT_STATUS_IS_OK(status)) {
4479                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4480                 correct = False;
4481         }
4482
4483         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4484         if (!NT_STATUS_IS_OK(status)) {
4485                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4486                 correct = False;
4487         }
4488         else if (strcmp(pname, fname)) {
4489                 printf("qfilename gave different name? [%s] [%s]\n",
4490                        fname, pname);
4491                 correct = False;
4492         }
4493
4494         cli_close(cli, fnum);
4495
4496         sleep(2);
4497
4498         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4499         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4500                           &fnum);
4501         if (!NT_STATUS_IS_OK(status)) {
4502                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4503                 return False;
4504         }
4505         cli_close(cli, fnum);
4506
4507         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4508                                 NULL);
4509         if (!NT_STATUS_IS_OK(status)) {
4510                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4511                 correct = False;
4512         } else {
4513                 time_t t = time(NULL);
4514
4515                 if (c_time != m_time) {
4516                         printf("create time=%s", ctime(&c_time));
4517                         printf("modify time=%s", ctime(&m_time));
4518                         printf("This system appears to have sticky create times\n");
4519                 }
4520                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4521                         printf("access time=%s", ctime(&a_time));
4522                         printf("This system appears to set a midnight access time\n");
4523                         correct = False;
4524                 }
4525
4526                 if (labs(m_time - t) > 60*60*24*7) {
4527                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4528                         correct = False;
4529                 }
4530         }
4531
4532
4533         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4534         cli_openx(cli, fname, 
4535                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4536         cli_close(cli, fnum);
4537         status = cli_qpathinfo2(cli,
4538                                 fname,
4539                                 &c_time_ts,
4540                                 &a_time_ts,
4541                                 &w_time_ts,
4542                                 &m_time_ts,
4543                                 &size,
4544                                 NULL,
4545                                 &ino,
4546                                 NULL);
4547         if (!NT_STATUS_IS_OK(status)) {
4548                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4549                 correct = False;
4550         } else {
4551                 if (w_time_ts.tv_sec < 60*60*24*2) {
4552                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4553                         printf("This system appears to set a initial 0 write time\n");
4554                         correct = False;
4555                 }
4556                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4557                         /* SMB2 should always return an inode. */
4558                         if (ino == 0) {
4559                                 printf("SMB2 bad inode (0)\n");
4560                                 correct = false;
4561                         }
4562                 } else {
4563                         /* SMB1 must always return zero here. */
4564                         if (ino != 0) {
4565                                 printf("SMB1 bad inode (!0)\n");
4566                                 correct = false;
4567                         }
4568                 }
4569         }
4570
4571         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4572
4573
4574         /* check if the server updates the directory modification time
4575            when creating a new file */
4576         status = cli_mkdir(cli, dname);
4577         if (!NT_STATUS_IS_OK(status)) {
4578                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4579                 correct = False;
4580         }
4581         sleep(3);
4582         status = cli_qpathinfo2(cli,
4583                                 "\\trans2\\",
4584                                 &c_time_ts,
4585                                 &a_time_ts,
4586                                 &w_time_ts,
4587                                 &m_time_ts,
4588                                 &size,
4589                                 NULL,
4590                                 NULL,
4591                                 NULL);
4592         if (!NT_STATUS_IS_OK(status)) {
4593                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4594                 correct = False;
4595         }
4596
4597         cli_openx(cli, fname2, 
4598                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4599         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4600         cli_close(cli, fnum);
4601         status = cli_qpathinfo2(cli,
4602                                 "\\trans2\\",
4603                                 &c_time_ts,
4604                                 &a_time_ts,
4605                                 &w_time_ts,
4606                                 &m_time2_ts,
4607                                 &size,
4608                                 NULL,
4609                                 NULL,
4610                                 NULL);
4611         if (!NT_STATUS_IS_OK(status)) {
4612                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4613                 correct = False;
4614         } else {
4615                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4616                     == 0) {
4617                         printf("This system does not update directory modification times\n");
4618                         correct = False;
4619                 }
4620         }
4621         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4622         cli_rmdir(cli, dname);
4623
4624         if (!torture_close_connection(cli)) {
4625                 correct = False;
4626         }
4627
4628         printf("trans2 test finished\n");
4629
4630         return correct;
4631 }
4632
4633 /*
4634   This checks new W2K calls.
4635 */
4636
4637 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4638 {
4639         uint8_t *buf = NULL;
4640         uint32_t len;
4641         NTSTATUS status;
4642
4643         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4644                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4645         if (!NT_STATUS_IS_OK(status)) {
4646                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4647                        nt_errstr(status));
4648         } else {
4649                 printf("qfileinfo: level %d, len = %u\n", level, len);
4650                 dump_data(0, (uint8_t *)buf, len);
4651                 printf("\n");
4652         }
4653         TALLOC_FREE(buf);
4654         return status;
4655 }
4656
4657 static bool run_w2ktest(int dummy)
4658 {
4659         struct cli_state *cli;
4660         uint16_t fnum;
4661         const char *fname = "\\w2ktest\\w2k.tst";
4662         int level;
4663         bool correct = True;
4664
4665         printf("starting w2k test\n");
4666
4667         if (!torture_open_connection(&cli, 0)) {
4668                 return False;
4669         }
4670
4671         cli_openx(cli, fname, 
4672                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4673
4674         for (level = 1004; level < 1040; level++) {
4675                 new_trans(cli, fnum, level);
4676         }
4677
4678         cli_close(cli, fnum);
4679
4680         if (!torture_close_connection(cli)) {
4681                 correct = False;
4682         }
4683
4684         printf("w2k test finished\n");
4685
4686         return correct;
4687 }
4688
4689
4690 /*
4691   this is a harness for some oplock tests
4692  */
4693 static bool run_oplock1(int dummy)
4694 {
4695         struct cli_state *cli1;
4696         const char *fname = "\\lockt1.lck";
4697         uint16_t fnum1;
4698         bool correct = True;
4699         NTSTATUS status;
4700
4701         printf("starting oplock test 1\n");
4702
4703         if (!torture_open_connection(&cli1, 0)) {
4704                 return False;
4705         }
4706
4707         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4708
4709         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4710
4711         cli1->use_oplocks = True;
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         cli1->use_oplocks = False;
4721
4722         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4723         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724
4725         status = cli_close(cli1, fnum1);
4726         if (!NT_STATUS_IS_OK(status)) {
4727                 printf("close2 failed (%s)\n", nt_errstr(status));
4728                 return False;
4729         }
4730
4731         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732         if (!NT_STATUS_IS_OK(status)) {
4733                 printf("unlink failed (%s)\n", nt_errstr(status));
4734                 return False;
4735         }
4736
4737         if (!torture_close_connection(cli1)) {
4738                 correct = False;
4739         }
4740
4741         printf("finished oplock test 1\n");
4742
4743         return correct;
4744 }
4745
4746 static bool run_oplock2(int dummy)
4747 {
4748         struct cli_state *cli1, *cli2;
4749         const char *fname = "\\lockt2.lck";
4750         uint16_t fnum1, fnum2;
4751         int saved_use_oplocks = use_oplocks;
4752         char buf[4];
4753         bool correct = True;
4754         volatile bool *shared_correct;
4755         size_t nread;
4756         NTSTATUS status;
4757
4758         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4759         *shared_correct = True;
4760
4761         use_level_II_oplocks = True;
4762         use_oplocks = True;
4763
4764         printf("starting oplock test 2\n");
4765
4766         if (!torture_open_connection(&cli1, 0)) {
4767                 use_level_II_oplocks = False;
4768                 use_oplocks = saved_use_oplocks;
4769                 return False;
4770         }
4771
4772         if (!torture_open_connection(&cli2, 1)) {
4773                 use_level_II_oplocks = False;
4774                 use_oplocks = saved_use_oplocks;
4775                 return False;
4776         }
4777
4778         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4779
4780         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4781         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4782
4783         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4784                           &fnum1);
4785         if (!NT_STATUS_IS_OK(status)) {
4786                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4787                 return False;
4788         }
4789
4790         /* Don't need the globals any more. */
4791         use_level_II_oplocks = False;
4792         use_oplocks = saved_use_oplocks;
4793
4794         if (fork() == 0) {
4795                 /* Child code */
4796                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4797                 if (!NT_STATUS_IS_OK(status)) {
4798                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4799                         *shared_correct = False;
4800                         exit(0);
4801                 }
4802
4803                 sleep(2);
4804
4805                 status = cli_close(cli2, fnum2);
4806                 if (!NT_STATUS_IS_OK(status)) {
4807                         printf("close2 failed (%s)\n", nt_errstr(status));
4808                         *shared_correct = False;
4809                 }
4810
4811                 exit(0);
4812         }
4813
4814         sleep(2);
4815
4816         /* Ensure cli1 processes the break. Empty file should always return 0
4817          * bytes.  */
4818         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4819         if (!NT_STATUS_IS_OK(status)) {
4820                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4821                 correct = false;
4822         } else if (nread != 0) {
4823                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4824                       (unsigned long)nread, 0);
4825                 correct = false;
4826         }
4827
4828         /* Should now be at level II. */
4829         /* Test if sending a write locks causes a break to none. */
4830         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4831         if (!NT_STATUS_IS_OK(status)) {
4832                 printf("lock failed (%s)\n", nt_errstr(status));
4833                 correct = False;
4834         }
4835
4836         cli_unlock(cli1, fnum1, 0, 4);
4837
4838         sleep(2);
4839
4840         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4841         if (!NT_STATUS_IS_OK(status)) {
4842                 printf("lock failed (%s)\n", nt_errstr(status));
4843                 correct = False;
4844         }
4845
4846         cli_unlock(cli1, fnum1, 0, 4);
4847
4848         sleep(2);
4849
4850         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4851
4852         status = cli_close(cli1, fnum1);
4853         if (!NT_STATUS_IS_OK(status)) {
4854                 printf("close1 failed (%s)\n", nt_errstr(status));
4855                 correct = False;
4856         }
4857
4858         sleep(4);
4859
4860         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4861         if (!NT_STATUS_IS_OK(status)) {
4862                 printf("unlink failed (%s)\n", nt_errstr(status));
4863                 correct = False;
4864         }
4865
4866         if (!torture_close_connection(cli1)) {
4867                 correct = False;
4868         }
4869
4870         if (!*shared_correct) {
4871                 correct = False;
4872         }
4873
4874         printf("finished oplock test 2\n");
4875
4876         return correct;
4877 }
4878
4879 struct oplock4_state {
4880         struct tevent_context *ev;
4881         struct cli_state *cli;
4882         bool *got_break;
4883         uint16_t *fnum2;
4884 };
4885
4886 static void oplock4_got_break(struct tevent_req *req);
4887 static void oplock4_got_open(struct tevent_req *req);
4888
4889 static bool run_oplock4(int dummy)
4890 {
4891         struct tevent_context *ev;
4892         struct cli_state *cli1, *cli2;
4893         struct tevent_req *oplock_req, *open_req;
4894         const char *fname = "\\lockt4.lck";
4895         const char *fname_ln = "\\lockt4_ln.lck";
4896         uint16_t fnum1, fnum2;
4897         int saved_use_oplocks = use_oplocks;
4898         NTSTATUS status;
4899         bool correct = true;
4900
4901         bool got_break;
4902
4903         struct oplock4_state *state;
4904
4905         printf("starting oplock test 4\n");
4906
4907         if (!torture_open_connection(&cli1, 0)) {
4908                 use_level_II_oplocks = false;
4909                 use_oplocks = saved_use_oplocks;
4910                 return false;
4911         }
4912
4913         if (!torture_open_connection(&cli2, 1)) {
4914                 use_level_II_oplocks = false;
4915                 use_oplocks = saved_use_oplocks;
4916                 return false;
4917         }
4918
4919         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4920         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4921
4922         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4923         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4924
4925         /* Create the file. */
4926         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4927                           &fnum1);
4928         if (!NT_STATUS_IS_OK(status)) {
4929                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4930                 return false;
4931         }
4932
4933         status = cli_close(cli1, fnum1);
4934         if (!NT_STATUS_IS_OK(status)) {
4935                 printf("close1 failed (%s)\n", nt_errstr(status));
4936                 return false;
4937         }
4938
4939         /* Now create a hardlink. */
4940         status = cli_hardlink(cli1, fname, fname_ln);
4941         if (!NT_STATUS_IS_OK(status)) {
4942                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4943                 return false;
4944         }
4945
4946         /* Prove that opening hardlinks cause deny modes to conflict. */
4947         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4948         if (!NT_STATUS_IS_OK(status)) {
4949                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4950                 return false;
4951         }
4952
4953         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4954         if (NT_STATUS_IS_OK(status)) {
4955                 printf("open of %s succeeded - should fail with sharing violation.\n",
4956                         fname_ln);
4957                 return false;
4958         }
4959
4960         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4961                 printf("open of %s should fail with sharing violation. Got %s\n",
4962                         fname_ln, nt_errstr(status));
4963                 return false;
4964         }
4965
4966         status = cli_close(cli1, fnum1);
4967         if (!NT_STATUS_IS_OK(status)) {
4968                 printf("close1 failed (%s)\n", nt_errstr(status));
4969                 return false;
4970         }
4971
4972         cli1->use_oplocks = true;
4973         cli2->use_oplocks = true;
4974
4975         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4976         if (!NT_STATUS_IS_OK(status)) {
4977                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4978                 return false;
4979         }
4980
4981         ev = samba_tevent_context_init(talloc_tos());
4982         if (ev == NULL) {
4983                 printf("tevent_context_init failed\n");
4984                 return false;
4985         }
4986
4987         state = talloc(ev, struct oplock4_state);
4988         if (state == NULL) {
4989                 printf("talloc failed\n");
4990                 return false;
4991         }
4992         state->ev = ev;
4993         state->cli = cli1;
4994         state->got_break = &got_break;
4995         state->fnum2 = &fnum2;
4996
4997         oplock_req = cli_smb_oplock_break_waiter_send(
4998                 talloc_tos(), ev, cli1);
4999         if (oplock_req == NULL) {
5000                 printf("cli_smb_oplock_break_waiter_send failed\n");
5001                 return false;
5002         }
5003         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5004
5005         open_req = cli_openx_send(
5006                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5007         if (open_req == NULL) {
5008                 printf("cli_openx_send failed\n");
5009                 return false;
5010         }
5011         tevent_req_set_callback(open_req, oplock4_got_open, state);
5012
5013         got_break = false;
5014         fnum2 = 0xffff;
5015
5016         while (!got_break || fnum2 == 0xffff) {
5017                 int ret;
5018                 ret = tevent_loop_once(ev);
5019                 if (ret == -1) {
5020                         printf("tevent_loop_once failed: %s\n",
5021                                strerror(errno));
5022                         return false;
5023                 }
5024         }
5025
5026         status = cli_close(cli2, fnum2);
5027         if (!NT_STATUS_IS_OK(status)) {
5028                 printf("close2 failed (%s)\n", nt_errstr(status));
5029                 correct = false;
5030         }
5031
5032         status = cli_close(cli1, fnum1);
5033         if (!NT_STATUS_IS_OK(status)) {
5034                 printf("close1 failed (%s)\n", nt_errstr(status));
5035                 correct = false;
5036         }
5037
5038         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5039         if (!NT_STATUS_IS_OK(status)) {
5040                 printf("unlink failed (%s)\n", nt_errstr(status));
5041                 correct = false;
5042         }
5043
5044         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5045         if (!NT_STATUS_IS_OK(status)) {
5046                 printf("unlink failed (%s)\n", nt_errstr(status));
5047                 correct = false;
5048         }
5049
5050         if (!torture_close_connection(cli1)) {
5051                 correct = false;
5052         }
5053
5054         if (!got_break) {
5055                 correct = false;
5056         }
5057
5058         printf("finished oplock test 4\n");
5059
5060         return correct;
5061 }
5062
5063 static void oplock4_got_break(struct tevent_req *req)
5064 {
5065         struct oplock4_state *state = tevent_req_callback_data(
5066                 req, struct oplock4_state);
5067         uint16_t fnum;
5068         uint8_t level;
5069         NTSTATUS status;
5070
5071         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5072         TALLOC_FREE(req);
5073         if (!NT_STATUS_IS_OK(status)) {
5074                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5075                        nt_errstr(status));
5076                 return;
5077         }
5078         *state->got_break = true;
5079
5080         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5081                                   NO_OPLOCK);
5082         if (req == NULL) {
5083                 printf("cli_oplock_ack_send failed\n");
5084                 return;
5085         }
5086 }
5087
5088 static void oplock4_got_open(struct tevent_req *req)
5089 {
5090         struct oplock4_state *state = tevent_req_callback_data(
5091                 req, struct oplock4_state);
5092         NTSTATUS status;
5093
5094         status = cli_openx_recv(req, state->fnum2);
5095         if (!NT_STATUS_IS_OK(status)) {
5096                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5097                 *state->fnum2 = 0xffff;
5098         }
5099 }
5100
5101 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5102
5103 struct oplock5_state {
5104         int pipe_down_fd;
5105 };
5106
5107 /*
5108  * Async open the file that has a kernel oplock, do an echo to get
5109  * that 100% across, close the file to signal to the child fd that the
5110  * oplock can be dropped, wait for the open reply.
5111  */
5112
5113 static void oplock5_opened(struct tevent_req *subreq);
5114 static void oplock5_pong(struct tevent_req *subreq);
5115 static void oplock5_timedout(struct tevent_req *subreq);
5116
5117 static struct tevent_req *oplock5_send(
5118         TALLOC_CTX *mem_ctx,
5119         struct tevent_context *ev,
5120         struct cli_state *cli,
5121         const char *fname,
5122         int pipe_down_fd)
5123 {
5124         struct tevent_req *req = NULL, *subreq = NULL;
5125         struct oplock5_state *state = NULL;
5126         static uint8_t data = 0;
5127
5128         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5129         if (req == NULL) {
5130                 return NULL;
5131         }
5132         state->pipe_down_fd = pipe_down_fd;
5133
5134         subreq = cli_ntcreate_send(
5135                 state,
5136                 ev,
5137                 cli,
5138                 fname,
5139                 0,                      /* CreatFlags */
5140                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5141                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5142                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5143                 FILE_OPEN,               /* CreateDisposition */
5144                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5145                 0,                       /* Impersonation */
5146                 0);                      /* SecurityFlags */
5147         if (tevent_req_nomem(subreq, req)) {
5148                 return tevent_req_post(req, ev);
5149         }
5150         tevent_req_set_callback(subreq, oplock5_opened, req);
5151
5152         subreq = cli_echo_send(
5153                 state,
5154                 ev,
5155                 cli,
5156                 1,
5157                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5158         if (tevent_req_nomem(subreq, req)) {
5159                 return tevent_req_post(req, ev);
5160         }
5161         tevent_req_set_callback(subreq, oplock5_pong, req);
5162
5163         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5164         if (tevent_req_nomem(subreq, req)) {
5165                 return tevent_req_post(req, ev);
5166         }
5167         tevent_req_set_callback(subreq, oplock5_timedout, req);
5168
5169         return req;
5170 }
5171
5172 static void oplock5_opened(struct tevent_req *subreq)
5173 {
5174         struct tevent_req *req = tevent_req_callback_data(
5175                 subreq, struct tevent_req);
5176         NTSTATUS status;
5177         uint16_t fnum;
5178
5179         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5180         TALLOC_FREE(subreq);
5181         if (tevent_req_nterror(req, status)) {
5182                 return;
5183         }
5184         tevent_req_done(req);
5185 }
5186
5187 static void oplock5_pong(struct tevent_req *subreq)
5188 {
5189         struct tevent_req *req = tevent_req_callback_data(
5190                 subreq, struct tevent_req);
5191         struct oplock5_state *state = tevent_req_data(
5192                 req, struct oplock5_state);
5193         NTSTATUS status;
5194
5195         status = cli_echo_recv(subreq);
5196         TALLOC_FREE(subreq);
5197         if (tevent_req_nterror(req, status)) {
5198                 return;
5199         }
5200
5201         close(state->pipe_down_fd);
5202 }
5203
5204 static void oplock5_timedout(struct tevent_req *subreq)
5205 {
5206         struct tevent_req *req = tevent_req_callback_data(
5207                 subreq, struct tevent_req);
5208         bool ok;
5209
5210         ok = tevent_wakeup_recv(subreq);
5211         TALLOC_FREE(subreq);
5212         if (!ok) {
5213                 tevent_req_oom(req);
5214                 return;
5215         }
5216         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5217 }
5218
5219 static NTSTATUS oplock5_recv(struct tevent_req *req)
5220 {
5221         return tevent_req_simple_recv_ntstatus(req);
5222 }
5223
5224 static bool run_oplock5(int dummy)
5225 {
5226         struct tevent_context *ev = NULL;
5227         struct tevent_req *req = NULL;
5228         struct cli_state *cli = NULL;
5229         const char *fname = "oplock5.txt";
5230         int pipe_down[2], pipe_up[2];
5231         pid_t child_pid;
5232         uint8_t c = '\0';
5233         NTSTATUS status;
5234         int ret;
5235         bool ok;
5236
5237         printf("starting oplock5\n");
5238
5239         if (local_path == NULL) {
5240                 d_fprintf(stderr, "oplock5 must be given a local path via "
5241                           "-l <localpath>\n");
5242                 return false;
5243         }
5244
5245         ret = pipe(pipe_down);
5246         if (ret == -1) {
5247                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5248                 return false;
5249         }
5250         ret = pipe(pipe_up);
5251         if (ret == -1) {
5252                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5253                 return false;
5254         }
5255
5256         child_pid = fork();
5257         if (child_pid == -1) {
5258                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5259                 return false;
5260         }
5261
5262         if (child_pid == 0) {
5263                 char *local_file = NULL;
5264                 int fd;
5265
5266                 close(pipe_down[1]);
5267                 close(pipe_up[0]);
5268
5269                 local_file = talloc_asprintf(
5270                         talloc_tos(), "%s/%s", local_path, fname);
5271                 if (local_file == 0) {
5272                         c = 1;
5273                         goto do_write;
5274                 }
5275                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5276                 if (fd == -1) {
5277                         d_fprintf(stderr,
5278                                   "open(%s) in child failed: %s\n",
5279                                   local_file,
5280                                   strerror(errno));
5281                         c = 2;
5282                         goto do_write;
5283                 }
5284
5285                 signal(SIGIO, SIG_IGN);
5286
5287                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5288                 if (ret == -1) {
5289                         d_fprintf(stderr,
5290                                   "SETLEASE in child failed: %s\n",
5291                                   strerror(errno));
5292                         c = 3;
5293                         goto do_write;
5294                 }
5295
5296         do_write:
5297                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5298                 if (ret == -1) {
5299                         d_fprintf(stderr,
5300                                   "sys_write failed: %s\n",
5301                                   strerror(errno));
5302                         exit(4);
5303                 }
5304                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5305                 if (ret == -1) {
5306                         d_fprintf(stderr,
5307                                   "sys_read failed: %s\n",
5308                                   strerror(errno));
5309                         exit(5);
5310                 }
5311                 exit(0);
5312         }
5313
5314         close(pipe_up[1]);
5315         close(pipe_down[0]);
5316
5317         ret = sys_read(pipe_up[0], &c, sizeof(c));
5318         if (ret != 1) {
5319                 d_fprintf(stderr,
5320                           "sys_read failed: %s\n",
5321                           strerror(errno));
5322                 return false;
5323         }
5324         if (c != 0) {
5325                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5326                 return false;
5327         }
5328
5329         ok = torture_open_connection(&cli, 0);
5330         if (!ok) {
5331                 d_fprintf(stderr, "torture_open_connection failed\n");
5332                 return false;
5333         }
5334
5335         ev = samba_tevent_context_init(talloc_tos());
5336         if (ev == NULL) {
5337                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5338                 return false;
5339         }
5340
5341         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5342         if (req == NULL) {
5343                 d_fprintf(stderr, "oplock5_send failed\n");
5344                 return false;
5345         }
5346
5347         ok = tevent_req_poll_ntstatus(req, ev, &status);
5348         if (!ok) {
5349                 d_fprintf(stderr,
5350                           "tevent_req_poll_ntstatus failed: %s\n",
5351                           nt_errstr(status));
5352                 return false;
5353         }
5354
5355         status = oplock5_recv(req);
5356         TALLOC_FREE(req);
5357         if (!NT_STATUS_IS_OK(status)) {
5358                 d_fprintf(stderr,
5359                           "oplock5 failed: %s\n",
5360                           nt_errstr(status));
5361                 return false;
5362         }
5363
5364         return true;
5365 }
5366
5367 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5368
5369 /*
5370   Test delete on close semantics.
5371  */
5372 static bool run_deletetest(int dummy)
5373 {
5374         struct cli_state *cli1 = NULL;
5375         struct cli_state *cli2 = NULL;
5376         const char *fname = "\\delete.file";
5377         uint16_t fnum1 = (uint16_t)-1;
5378         uint16_t fnum2 = (uint16_t)-1;
5379         bool correct = false;
5380         NTSTATUS status;
5381
5382         printf("starting delete test\n");
5383
5384         if (!torture_open_connection(&cli1, 0)) {
5385                 return False;
5386         }
5387
5388         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5389
5390         /* Test 1 - this should delete the file on close. */
5391
5392         cli_setatr(cli1, fname, 0, 0);
5393         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5394
5395         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5396                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5397                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5398         if (!NT_STATUS_IS_OK(status)) {
5399                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5400                 goto fail;
5401         }
5402
5403         status = cli_close(cli1, fnum1);
5404         if (!NT_STATUS_IS_OK(status)) {
5405                 printf("[1] close failed (%s)\n", nt_errstr(status));
5406                 goto fail;
5407         }
5408
5409         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5410         if (NT_STATUS_IS_OK(status)) {
5411                 printf("[1] open of %s succeeded (should fail)\n", fname);
5412                 goto fail;
5413         }
5414
5415         printf("first delete on close test succeeded.\n");
5416
5417         /* Test 2 - this should delete the file on close. */
5418
5419         cli_setatr(cli1, fname, 0, 0);
5420         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5421
5422         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5423                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5424                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5425         if (!NT_STATUS_IS_OK(status)) {
5426                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5427                 goto fail;
5428         }
5429
5430         status = cli_nt_delete_on_close(cli1, fnum1, true);
5431         if (!NT_STATUS_IS_OK(status)) {
5432                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5433                 goto fail;
5434         }
5435
5436         status = cli_close(cli1, fnum1);
5437         if (!NT_STATUS_IS_OK(status)) {
5438                 printf("[2] close failed (%s)\n", nt_errstr(status));
5439                 goto fail;
5440         }
5441
5442         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5443         if (NT_STATUS_IS_OK(status)) {
5444                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5445                 status = cli_close(cli1, fnum1);
5446                 if (!NT_STATUS_IS_OK(status)) {
5447                         printf("[2] close failed (%s)\n", nt_errstr(status));
5448                 }
5449                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5450                 goto fail;
5451         }
5452
5453         printf("second delete on close test succeeded.\n");
5454
5455         /* Test 3 - ... */
5456         cli_setatr(cli1, fname, 0, 0);
5457         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5458
5459         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5460                               FILE_ATTRIBUTE_NORMAL,
5461                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5462                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5463         if (!NT_STATUS_IS_OK(status)) {
5464                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5465                 goto fail;
5466         }
5467
5468         /* This should fail with a sharing violation - open for delete is only compatible
5469            with SHARE_DELETE. */
5470
5471         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5472                               FILE_ATTRIBUTE_NORMAL,
5473                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5474                               FILE_OPEN, 0, 0, &fnum2, NULL);
5475         if (NT_STATUS_IS_OK(status)) {
5476                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5477                 goto fail;
5478         }
5479
5480         /* This should succeed. */
5481         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5482                              FILE_ATTRIBUTE_NORMAL,
5483                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5484                              FILE_OPEN, 0, 0, &fnum2, NULL);
5485         if (!NT_STATUS_IS_OK(status)) {
5486                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5487                 goto fail;
5488         }
5489
5490         status = cli_nt_delete_on_close(cli1, fnum1, true);
5491         if (!NT_STATUS_IS_OK(status)) {
5492                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5493                 goto fail;
5494         }
5495
5496         status = cli_close(cli1, fnum1);
5497         if (!NT_STATUS_IS_OK(status)) {
5498                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5499                 goto fail;
5500         }
5501
5502         status = cli_close(cli1, fnum2);
5503         if (!NT_STATUS_IS_OK(status)) {
5504                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5505                 goto fail;
5506         }
5507
5508         /* This should fail - file should no longer be there. */
5509
5510         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5511         if (NT_STATUS_IS_OK(status)) {
5512                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5513                 status = cli_close(cli1, fnum1);
5514                 if (!NT_STATUS_IS_OK(status)) {
5515                         printf("[3] close failed (%s)\n", nt_errstr(status));
5516                 }
5517                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5518                 goto fail;
5519         }
5520
5521         printf("third delete on close test succeeded.\n");
5522
5523         /* Test 4 ... */
5524         cli_setatr(cli1, fname, 0, 0);
5525         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5526
5527         status = cli_ntcreate(cli1, fname, 0,
5528                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5529                               FILE_ATTRIBUTE_NORMAL,
5530                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5531                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5532         if (!NT_STATUS_IS_OK(status)) {
5533                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5534                 goto fail;
5535         }
5536
5537         /* This should succeed. */
5538         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5539                              FILE_ATTRIBUTE_NORMAL,
5540                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5541                              FILE_OPEN, 0, 0, &fnum2, NULL);
5542         if (!NT_STATUS_IS_OK(status)) {
5543                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5544                 goto fail;
5545         }
5546
5547         status = cli_close(cli1, fnum2);
5548         if (!NT_STATUS_IS_OK(status)) {
5549                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5550                 goto fail;
5551         }
5552
5553         status = cli_nt_delete_on_close(cli1, fnum1, true);
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5556                 goto fail;
5557         }
5558
5559         /* This should fail - no more opens once delete on close set. */
5560         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5561                               FILE_ATTRIBUTE_NORMAL,
5562                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5563                               FILE_OPEN, 0, 0, &fnum2, NULL);
5564         if (NT_STATUS_IS_OK(status)) {
5565                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5566                 goto fail;
5567         }
5568
5569         status = cli_close(cli1, fnum1);
5570         if (!NT_STATUS_IS_OK(status)) {
5571                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5572                 goto fail;
5573         }
5574
5575         printf("fourth delete on close test succeeded.\n");
5576
5577         /* Test 5 ... */
5578         cli_setatr(cli1, fname, 0, 0);
5579         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5580
5581         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5582         if (!NT_STATUS_IS_OK(status)) {
5583                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5584                 goto fail;
5585         }
5586
5587         /* This should fail - only allowed on NT opens with DELETE access. */
5588
5589         status = cli_nt_delete_on_close(cli1, fnum1, true);
5590         if (NT_STATUS_IS_OK(status)) {
5591                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5592                 goto fail;
5593         }
5594
5595         status = cli_close(cli1, fnum1);
5596         if (!NT_STATUS_IS_OK(status)) {
5597                 printf("[5] close failed (%s)\n", nt_errstr(status));
5598                 goto fail;
5599         }
5600
5601         printf("fifth delete on close test succeeded.\n");
5602
5603         /* Test 6 ... */
5604         cli_setatr(cli1, fname, 0, 0);
5605         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5606
5607         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5608                              FILE_ATTRIBUTE_NORMAL,
5609                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5610                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5611         if (!NT_STATUS_IS_OK(status)) {
5612                 printf("[6] open of %s failed (%s)\n", fname,
5613                        nt_errstr(status));
5614                 goto fail;
5615         }
5616
5617         /* This should fail - only allowed on NT opens with DELETE access. */
5618
5619         status = cli_nt_delete_on_close(cli1, fnum1, true);
5620         if (NT_STATUS_IS_OK(status)) {
5621                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5622                 goto fail;
5623         }
5624
5625         status = cli_close(cli1, fnum1);
5626         if (!NT_STATUS_IS_OK(status)) {
5627                 printf("[6] close failed (%s)\n", nt_errstr(status));
5628                 goto fail;
5629         }
5630
5631         printf("sixth delete on close test succeeded.\n");
5632
5633         /* Test 7 ... */
5634         cli_setatr(cli1, fname, 0, 0);
5635         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5636
5637         status = cli_ntcreate(cli1, fname, 0,
5638                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5639                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5640                               0, 0, &fnum1, NULL);
5641         if (!NT_STATUS_IS_OK(status)) {
5642                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5643                 goto fail;
5644         }
5645
5646         status = cli_nt_delete_on_close(cli1, fnum1, true);
5647         if (!NT_STATUS_IS_OK(status)) {
5648                 printf("[7] setting delete_on_close on file failed !\n");
5649                 goto fail;
5650         }
5651
5652         status = cli_nt_delete_on_close(cli1, fnum1, false);
5653         if (!NT_STATUS_IS_OK(status)) {
5654                 printf("[7] unsetting delete_on_close on file failed !\n");
5655                 goto fail;
5656         }
5657
5658         status = cli_close(cli1, fnum1);
5659         if (!NT_STATUS_IS_OK(status)) {
5660                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5661                 goto fail;
5662         }
5663
5664         /* This next open should succeed - we reset the flag. */
5665         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5666         if (!NT_STATUS_IS_OK(status)) {
5667                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5668                 goto fail;
5669         }
5670
5671         status = cli_close(cli1, fnum1);
5672         if (!NT_STATUS_IS_OK(status)) {
5673                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5674                 goto fail;
5675         }
5676
5677         printf("seventh delete on close test succeeded.\n");
5678
5679         /* Test 8 ... */
5680         cli_setatr(cli1, fname, 0, 0);
5681         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5682
5683         if (!torture_open_connection(&cli2, 1)) {
5684                 printf("[8] failed to open second connection.\n");
5685                 goto fail;
5686         }
5687
5688         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5689
5690         status = cli_ntcreate(cli1, fname, 0,
5691                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5692                              FILE_ATTRIBUTE_NORMAL,
5693                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5694                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5695         if (!NT_STATUS_IS_OK(status)) {
5696                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5697                 goto fail;
5698         }
5699
5700         status = cli_ntcreate(cli2, fname, 0,
5701                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5702                              FILE_ATTRIBUTE_NORMAL,
5703                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5704                              FILE_OPEN, 0, 0, &fnum2, NULL);
5705         if (!NT_STATUS_IS_OK(status)) {
5706                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5707                 goto fail;
5708         }
5709
5710         status = cli_nt_delete_on_close(cli1, fnum1, true);
5711         if (!NT_STATUS_IS_OK(status)) {
5712                 printf("[8] setting delete_on_close on file failed !\n");
5713                 goto fail;
5714         }
5715
5716         status = cli_close(cli1, fnum1);
5717         if (!NT_STATUS_IS_OK(status)) {
5718                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5719                 goto fail;
5720         }
5721
5722         status = cli_close(cli2, fnum2);
5723         if (!NT_STATUS_IS_OK(status)) {
5724                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5725                 goto fail;
5726         }
5727
5728         /* This should fail.. */
5729         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5730         if (NT_STATUS_IS_OK(status)) {
5731                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5732                 goto fail;
5733         }
5734
5735         printf("eighth delete on close test succeeded.\n");
5736
5737         /* Test 9 ... */
5738
5739         /* This should fail - we need to set DELETE_ACCESS. */
5740         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5741                               FILE_ATTRIBUTE_NORMAL,
5742                               FILE_SHARE_NONE,
5743                               FILE_OVERWRITE_IF,
5744                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5745         if (NT_STATUS_IS_OK(status)) {
5746                 printf("[9] open of %s succeeded should have failed!\n", fname);
5747                 goto fail;
5748         }
5749
5750         printf("ninth delete on close test succeeded.\n");
5751
5752         /* Test 10 ... */
5753
5754         status = cli_ntcreate(cli1, fname, 0,
5755                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5756                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5757                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5758                              0, &fnum1, NULL);
5759         if (!NT_STATUS_IS_OK(status)) {
5760                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5761                 goto fail;
5762         }
5763
5764         /* This should delete the file. */
5765         status = cli_close(cli1, fnum1);
5766         if (!NT_STATUS_IS_OK(status)) {
5767                 printf("[10] close failed (%s)\n", nt_errstr(status));
5768                 goto fail;
5769         }
5770
5771         /* This should fail.. */
5772         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5773         if (NT_STATUS_IS_OK(status)) {
5774                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5775                 goto fail;
5776         }
5777
5778         printf("tenth delete on close test succeeded.\n");
5779
5780         /* Test 11 ... */
5781
5782         cli_setatr(cli1, fname, 0, 0);
5783         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5784
5785         /* Can we open a read-only file with delete access? */
5786
5787         /* Create a readonly file. */
5788         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5789                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5790                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5793                 goto fail;
5794         }
5795
5796         status = cli_close(cli1, fnum1);
5797         if (!NT_STATUS_IS_OK(status)) {
5798                 printf("[11] close failed (%s)\n", nt_errstr(status));
5799                 goto fail;
5800         }
5801
5802         /* Now try open for delete access. */
5803         status = cli_ntcreate(cli1, fname, 0,
5804                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5805                              0,
5806                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5807                              FILE_OPEN, 0, 0, &fnum1, NULL);
5808         if (!NT_STATUS_IS_OK(status)) {
5809                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5810                 goto fail;
5811         }
5812
5813         cli_close(cli1, fnum1);
5814
5815         printf("eleventh delete on close test succeeded.\n");
5816
5817         /*
5818          * Test 12
5819          * like test 4 but with initial delete on close
5820          */
5821
5822         cli_setatr(cli1, fname, 0, 0);
5823         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5824
5825         status = cli_ntcreate(cli1, fname, 0,
5826                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5827                               FILE_ATTRIBUTE_NORMAL,
5828                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5829                               FILE_OVERWRITE_IF,
5830                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5831         if (!NT_STATUS_IS_OK(status)) {
5832                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5833                 goto fail;
5834         }
5835
5836         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5837                               FILE_ATTRIBUTE_NORMAL,
5838                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5839                               FILE_OPEN, 0, 0, &fnum2, NULL);
5840         if (!NT_STATUS_IS_OK(status)) {
5841                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5842                 goto fail;
5843         }
5844
5845         status = cli_close(cli1, fnum2);
5846         if (!NT_STATUS_IS_OK(status)) {
5847                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5848                 goto fail;
5849         }
5850
5851         status = cli_nt_delete_on_close(cli1, fnum1, true);
5852         if (!NT_STATUS_IS_OK(status)) {
5853                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5854                 goto fail;
5855         }
5856
5857         /* This should fail - no more opens once delete on close set. */
5858         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5859                               FILE_ATTRIBUTE_NORMAL,
5860                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5861                               FILE_OPEN, 0, 0, &fnum2, NULL);
5862         if (NT_STATUS_IS_OK(status)) {
5863                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5864                 goto fail;
5865         }
5866
5867         status = cli_nt_delete_on_close(cli1, fnum1, false);
5868         if (!NT_STATUS_IS_OK(status)) {
5869                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5870                 goto fail;
5871         }
5872
5873         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5874                               FILE_ATTRIBUTE_NORMAL,
5875                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5876                               FILE_OPEN, 0, 0, &fnum2, NULL);
5877         if (!NT_STATUS_IS_OK(status)) {
5878                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5879                 goto fail;
5880         }
5881
5882         status = cli_close(cli1, fnum2);
5883         if (!NT_STATUS_IS_OK(status)) {
5884                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5885                 goto fail;
5886         }
5887
5888         status = cli_close(cli1, fnum1);
5889         if (!NT_STATUS_IS_OK(status)) {
5890                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5891                 goto fail;
5892         }
5893
5894         /*
5895          * setting delete on close on the handle does
5896          * not unset the initial delete on close...
5897          */
5898         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5899                               FILE_ATTRIBUTE_NORMAL,
5900                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5901                               FILE_OPEN, 0, 0, &fnum2, NULL);
5902         if (NT_STATUS_IS_OK(status)) {
5903                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5904                 goto fail;
5905         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5906                 printf("ntcreate returned %s, expected "
5907                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5908                        nt_errstr(status));
5909                 goto fail;
5910         }
5911
5912         printf("twelfth delete on close test succeeded.\n");
5913
5914
5915         printf("finished delete test\n");
5916
5917         correct = true;
5918
5919   fail:
5920         /* FIXME: This will crash if we aborted before cli2 got
5921          * initialized, because these functions don't handle
5922          * uninitialized connections. */
5923
5924         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5925         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5926         cli_setatr(cli1, fname, 0, 0);
5927         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5928
5929         if (cli1 && !torture_close_connection(cli1)) {
5930                 correct = False;
5931         }
5932         if (cli2 && !torture_close_connection(cli2)) {
5933                 correct = False;
5934         }
5935         return correct;
5936 }
5937
5938 struct delete_stream_state {
5939         bool closed;
5940 };
5941
5942 static void delete_stream_unlinked(struct tevent_req *subreq);
5943 static void delete_stream_closed(struct tevent_req *subreq);
5944
5945 static struct tevent_req *delete_stream_send(
5946         TALLOC_CTX *mem_ctx,
5947         struct tevent_context *ev,
5948         struct cli_state *cli,
5949         const char *base_fname,
5950         uint16_t stream_fnum)
5951 {
5952         struct tevent_req *req = NULL, *subreq = NULL;
5953         struct delete_stream_state *state = NULL;
5954
5955         req = tevent_req_create(
5956                 mem_ctx, &state, struct delete_stream_state);
5957         if (req == NULL) {
5958                 return NULL;
5959         }
5960
5961         subreq = cli_unlink_send(
5962                 state,
5963                 ev,
5964                 cli,
5965                 base_fname,
5966                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5967         if (tevent_req_nomem(subreq, req)) {
5968                 return tevent_req_post(req, ev);
5969         }
5970         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5971
5972         subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5973         if (tevent_req_nomem(subreq, req)) {
5974                 return tevent_req_post(req, ev);
5975         }
5976         tevent_req_set_callback(subreq, delete_stream_closed, req);
5977
5978         return req;
5979 }
5980
5981 static void delete_stream_unlinked(struct tevent_req *subreq)
5982 {
5983         struct tevent_req *req = tevent_req_callback_data(
5984                 subreq, struct tevent_req);
5985         struct delete_stream_state *state = tevent_req_data(
5986                 req, struct delete_stream_state);
5987         NTSTATUS status;
5988
5989         status = cli_unlink_recv(subreq);
5990         TALLOC_FREE(subreq);
5991         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5992                 printf("cli_unlink returned %s\n",
5993                        nt_errstr(status));
5994                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5995                 return;
5996         }
5997         if (!state->closed) {
5998                 /* close reply should have come in first */
5999                 printf("Not closed\n");
6000                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6001                 return;
6002         }
6003         tevent_req_done(req);
6004 }
6005
6006 static void delete_stream_closed(struct tevent_req *subreq)
6007 {
6008         struct tevent_req *req = tevent_req_callback_data(
6009                 subreq, struct tevent_req);
6010         struct delete_stream_state *state = tevent_req_data(
6011                 req, struct delete_stream_state);
6012         NTSTATUS status;
6013
6014         status = cli_close_recv(subreq);
6015         TALLOC_FREE(subreq);
6016         if (tevent_req_nterror(req, status)) {
6017                 return;
6018         }
6019         /* also waiting for the unlink to come back */
6020         state->closed = true;
6021 }
6022
6023 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6024 {
6025         return tevent_req_simple_recv_ntstatus(req);
6026 }
6027
6028 static bool run_delete_stream(int dummy)
6029 {
6030         struct tevent_context *ev = NULL;
6031         struct tevent_req *req = NULL;
6032         struct cli_state *cli = NULL;
6033         const char fname[] = "delete_stream";
6034         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6035         uint16_t fnum1, fnum2;
6036         NTSTATUS status;
6037         bool ok;
6038
6039         printf("Starting stream delete test\n");
6040
6041         ok = torture_open_connection(&cli, 0);
6042         if (!ok) {
6043                 return false;
6044         }
6045
6046         cli_setatr(cli, fname, 0, 0);
6047         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6048
6049         /* Create the file. */
6050         status = cli_ntcreate(
6051                 cli,
6052                 fname,
6053                 0,
6054                 READ_CONTROL_ACCESS,
6055                 0,
6056                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6057                 FILE_CREATE,
6058                 0x0,
6059                 0x0,
6060                 &fnum1,
6061                 NULL);
6062         if (!NT_STATUS_IS_OK(status)) {
6063                 d_fprintf(stderr,
6064                           "cli_ntcreate of %s failed (%s)\n",
6065                           fname,
6066                           nt_errstr(status));
6067                 return false;
6068         }
6069         status = cli_close(cli, fnum1);
6070         if (!NT_STATUS_IS_OK(status)) {
6071                 d_fprintf(stderr,
6072                           "cli_close of %s failed (%s)\n",
6073                           fname,
6074                           nt_errstr(status));
6075                 return false;
6076         }
6077
6078         /* Now create the stream. */
6079         status = cli_ntcreate(
6080                 cli,
6081                 fname_stream,
6082                 0,
6083                 FILE_WRITE_DATA,
6084                 0,
6085                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6086                 FILE_CREATE,
6087                 0x0,
6088                 0x0,
6089                 &fnum1,
6090                 NULL);
6091
6092         if (!NT_STATUS_IS_OK(status)) {
6093                 d_fprintf(stderr,
6094                           "cli_ntcreate of %s failed (%s)\n",
6095                           fname_stream,
6096                           nt_errstr(status));
6097                 return false;
6098         }
6099
6100         /* open it a second time */
6101
6102         status = cli_ntcreate(
6103                 cli,
6104                 fname_stream,
6105                 0,
6106                 FILE_WRITE_DATA,
6107                 0,
6108                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6109                 FILE_OPEN,
6110                 0x0,
6111                 0x0,
6112                 &fnum2,
6113                 NULL);
6114
6115         if (!NT_STATUS_IS_OK(status)) {
6116                 d_fprintf(stderr,
6117                           "2nd cli_ntcreate of %s failed (%s)\n",
6118                           fname_stream,
6119                           nt_errstr(status));
6120                 return false;
6121         }
6122
6123         ev = samba_tevent_context_init(talloc_tos());
6124         if (ev == NULL) {
6125                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6126                 return false;
6127         }
6128
6129         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6130         if (req == NULL) {
6131                 d_fprintf(stderr, "delete_stream_send failed\n");
6132                 return false;
6133         }
6134
6135         ok = tevent_req_poll_ntstatus(req, ev, &status);
6136         if (!ok) {
6137                 d_fprintf(stderr,
6138                           "tevent_req_poll_ntstatus failed: %s\n",
6139                           nt_errstr(status));
6140                 return false;
6141         }
6142
6143         status = delete_stream_recv(req);
6144         TALLOC_FREE(req);
6145         if (!NT_STATUS_IS_OK(status)) {
6146                 d_fprintf(stderr,
6147                           "delete_stream failed: %s\n",
6148                           nt_errstr(status));
6149                 return false;
6150         }
6151
6152         status = cli_close(cli, fnum2);
6153         if (!NT_STATUS_IS_OK(status)) {
6154                 d_fprintf(stderr,
6155                           "close failed: %s\n",
6156                           nt_errstr(status));
6157                 return false;
6158         }
6159
6160         status = cli_unlink(
6161                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6162         if (!NT_STATUS_IS_OK(status)) {
6163                 d_fprintf(stderr,
6164                           "unlink failed: %s\n",
6165                           nt_errstr(status));
6166                 return false;
6167         }
6168
6169         return true;
6170 }
6171
6172 /*
6173   Exercise delete on close semantics - use on the PRINT1 share in torture
6174   testing.
6175  */
6176 static bool run_delete_print_test(int dummy)
6177 {
6178         struct cli_state *cli1 = NULL;
6179         const char *fname = "print_delete.file";
6180         uint16_t fnum1 = (uint16_t)-1;
6181         bool correct = false;
6182         const char *buf = "print file data\n";
6183         NTSTATUS status;
6184
6185         printf("starting print delete test\n");
6186
6187         if (!torture_open_connection(&cli1, 0)) {
6188                 return false;
6189         }
6190
6191         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6192
6193         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6194                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6195                               0, 0, &fnum1, NULL);
6196         if (!NT_STATUS_IS_OK(status)) {
6197                 printf("open of %s failed (%s)\n",
6198                         fname,
6199                         nt_errstr(status));
6200                 goto fail;
6201         }
6202
6203         status = cli_writeall(cli1,
6204                         fnum1,
6205                         0,
6206                         (const uint8_t *)buf,
6207                         0, /* offset */
6208                         strlen(buf), /* size */
6209                         NULL);
6210         if (!NT_STATUS_IS_OK(status)) {
6211                 printf("writing print file data failed (%s)\n",
6212                         nt_errstr(status));
6213                 goto fail;
6214         }
6215
6216         status = cli_nt_delete_on_close(cli1, fnum1, true);
6217         if (!NT_STATUS_IS_OK(status)) {
6218                 printf("setting delete_on_close failed (%s)\n",
6219                         nt_errstr(status));
6220                 goto fail;
6221         }
6222
6223         status = cli_close(cli1, fnum1);
6224         if (!NT_STATUS_IS_OK(status)) {
6225                 printf("close failed (%s)\n", nt_errstr(status));
6226                 goto fail;
6227         }
6228
6229         printf("finished print delete test\n");
6230
6231         correct = true;
6232
6233   fail:
6234
6235         if (fnum1 != (uint16_t)-1) {
6236                 cli_close(cli1, fnum1);
6237         }
6238
6239         if (cli1 && !torture_close_connection(cli1)) {
6240                 correct = false;
6241         }
6242         return correct;
6243 }
6244
6245 static bool run_deletetest_ln(int dummy)
6246 {
6247         struct cli_state *cli;
6248         const char *fname = "\\delete1";
6249         const char *fname_ln = "\\delete1_ln";
6250         uint16_t fnum;
6251         uint16_t fnum1;
6252         NTSTATUS status;
6253         bool correct = true;
6254         time_t t;
6255
6256         printf("starting deletetest-ln\n");
6257
6258         if (!torture_open_connection(&cli, 0)) {
6259                 return false;
6260         }
6261
6262         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6263         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6264
6265         smbXcli_conn_set_sockopt(cli->conn, sockops);
6266
6267         /* Create the file. */
6268         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6269         if (!NT_STATUS_IS_OK(status)) {
6270                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6271                 return false;
6272         }
6273
6274         status = cli_close(cli, fnum);
6275         if (!NT_STATUS_IS_OK(status)) {
6276                 printf("close1 failed (%s)\n", nt_errstr(status));
6277                 return false;
6278         }
6279
6280         /* Now create a hardlink. */
6281         status = cli_hardlink(cli, fname, fname_ln);
6282         if (!NT_STATUS_IS_OK(status)) {
6283                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6284                 return false;
6285         }
6286
6287         /* Open the original file. */
6288         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6289                         FILE_ATTRIBUTE_NORMAL,
6290                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6291                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6292         if (!NT_STATUS_IS_OK(status)) {
6293                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6294                 return false;
6295         }
6296
6297         /* Unlink the hard link path. */
6298         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6299                         FILE_ATTRIBUTE_NORMAL,
6300                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6301                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6302         if (!NT_STATUS_IS_OK(status)) {
6303                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6304                 return false;
6305         }
6306         status = cli_nt_delete_on_close(cli, fnum1, true);
6307         if (!NT_STATUS_IS_OK(status)) {
6308                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6309                         __location__, fname_ln, nt_errstr(status));
6310                 return false;
6311         }
6312
6313         status = cli_close(cli, fnum1);
6314         if (!NT_STATUS_IS_OK(status)) {
6315                 printf("close %s failed (%s)\n",
6316                         fname_ln, nt_errstr(status));
6317                 return false;
6318         }
6319
6320         status = cli_close(cli, fnum);
6321         if (!NT_STATUS_IS_OK(status)) {
6322                 printf("close %s failed (%s)\n",
6323                         fname, nt_errstr(status));
6324                 return false;
6325         }
6326
6327         /* Ensure the original file is still there. */
6328         status = cli_getatr(cli, fname, NULL, NULL, &t);
6329         if (!NT_STATUS_IS_OK(status)) {
6330                 printf("%s getatr on file %s failed (%s)\n",
6331                         __location__,
6332                         fname,
6333                         nt_errstr(status));
6334                 correct = False;
6335         }
6336
6337         /* Ensure the link path is gone. */
6338         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6339         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6340                 printf("%s, getatr for file %s returned wrong error code %s "
6341                         "- should have been deleted\n",
6342                         __location__,
6343                         fname_ln, nt_errstr(status));
6344                 correct = False;
6345         }
6346
6347         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6348         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6349
6350         if (!torture_close_connection(cli)) {
6351                 correct = false;
6352         }
6353
6354         printf("finished deletetest-ln\n");
6355
6356         return correct;
6357 }
6358
6359 /*
6360   print out server properties
6361  */
6362 static bool run_properties(int dummy)
6363 {
6364         struct cli_state *cli;
6365         bool correct = True;
6366
6367         printf("starting properties test\n");
6368
6369         ZERO_STRUCT(cli);
6370
6371         if (!torture_open_connection(&cli, 0)) {
6372                 return False;
6373         }
6374
6375         smbXcli_conn_set_sockopt(cli->conn, sockops);
6376
6377         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6378
6379         if (!torture_close_connection(cli)) {
6380                 correct = False;
6381         }
6382
6383         return correct;
6384 }
6385
6386
6387
6388 /* FIRST_DESIRED_ACCESS   0xf019f */
6389 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6390                                FILE_READ_EA|                           /* 0xf */ \
6391                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6392                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6393                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6394                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6395 /* SECOND_DESIRED_ACCESS  0xe0080 */
6396 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6397                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6398                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6399
6400 #if 0
6401 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6402                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6403                                FILE_READ_DATA|\
6404                                WRITE_OWNER_ACCESS                      /* */
6405 #endif
6406
6407 /*
6408   Test ntcreate calls made by xcopy
6409  */
6410 static bool run_xcopy(int dummy)
6411 {
6412         static struct cli_state *cli1;
6413         const char *fname = "\\test.txt";
6414         bool correct = True;
6415         uint16_t fnum1, fnum2;
6416         NTSTATUS status;
6417
6418         printf("starting xcopy test\n");
6419
6420         if (!torture_open_connection(&cli1, 0)) {
6421                 return False;
6422         }
6423
6424         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6425                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6426                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6427         if (!NT_STATUS_IS_OK(status)) {
6428                 printf("First open failed - %s\n", nt_errstr(status));
6429                 return False;
6430         }
6431
6432         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6433                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6434                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6435         if (!NT_STATUS_IS_OK(status)) {
6436                 printf("second open failed - %s\n", nt_errstr(status));
6437                 return False;
6438         }
6439
6440         if (!torture_close_connection(cli1)) {
6441                 correct = False;
6442         }
6443
6444         return correct;
6445 }
6446
6447 /*
6448   Test rename on files open with share delete and no share delete.
6449  */
6450 static bool run_rename(int dummy)
6451 {
6452         static struct cli_state *cli1;
6453         const char *fname = "\\test.txt";
6454         const char *fname1 = "\\test1.txt";
6455         bool correct = True;
6456         uint16_t fnum1;
6457         uint32_t attr;
6458         NTSTATUS status;
6459
6460         printf("starting rename test\n");
6461
6462         if (!torture_open_connection(&cli1, 0)) {
6463                 return False;
6464         }
6465
6466         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6467         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468
6469         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6470                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6471                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6472         if (!NT_STATUS_IS_OK(status)) {
6473                 printf("First open failed - %s\n", nt_errstr(status));
6474                 return False;
6475         }
6476
6477         status = cli_rename(cli1, fname, fname1, false);
6478         if (!NT_STATUS_IS_OK(status)) {
6479                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6480         } else {
6481                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6482                 correct = False;
6483         }
6484
6485         status = cli_close(cli1, fnum1);
6486         if (!NT_STATUS_IS_OK(status)) {
6487                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6488                 return False;
6489         }
6490
6491         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6492         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6493         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6494 #if 0
6495                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6496 #else
6497                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6498 #endif
6499                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6500         if (!NT_STATUS_IS_OK(status)) {
6501                 printf("Second open failed - %s\n", nt_errstr(status));
6502                 return False;
6503         }
6504
6505         status = cli_rename(cli1, fname, fname1, false);
6506         if (!NT_STATUS_IS_OK(status)) {
6507                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6508                 correct = False;
6509         } else {
6510                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6511         }
6512
6513         status = cli_close(cli1, fnum1);
6514         if (!NT_STATUS_IS_OK(status)) {
6515                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6516                 return False;
6517         }
6518
6519         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6520         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6521
6522         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6523                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6524                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6525         if (!NT_STATUS_IS_OK(status)) {
6526                 printf("Third open failed - %s\n", nt_errstr(status));
6527                 return False;
6528         }
6529
6530
6531         status = cli_rename(cli1, fname, fname1, false);
6532         if (!NT_STATUS_IS_OK(status)) {
6533                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6534                 correct = False;
6535         } else {
6536                 printf("Third rename succeeded (SHARE_NONE)\n");
6537         }
6538
6539         status = cli_close(cli1, fnum1);
6540         if (!NT_STATUS_IS_OK(status)) {
6541                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6542                 return False;
6543         }
6544
6545         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6546         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6547
6548         /*----*/
6549
6550         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6551                               FILE_ATTRIBUTE_NORMAL,
6552                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6553                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6554         if (!NT_STATUS_IS_OK(status)) {
6555                 printf("Fourth open failed - %s\n", nt_errstr(status));
6556                 return False;
6557         }
6558
6559         status = cli_rename(cli1, fname, fname1, false);
6560         if (!NT_STATUS_IS_OK(status)) {
6561                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6562         } else {
6563                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6564                 correct = False;
6565         }
6566
6567         status = cli_close(cli1, fnum1);
6568         if (!NT_STATUS_IS_OK(status)) {
6569                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6570                 return False;
6571         }
6572
6573         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6574         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6575
6576         /*--*/
6577
6578         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6579                          FILE_ATTRIBUTE_NORMAL,
6580                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6581                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6582         if (!NT_STATUS_IS_OK(status)) {
6583                 printf("Fifth open failed - %s\n", nt_errstr(status));
6584                 return False;
6585         }
6586
6587         status = cli_rename(cli1, fname, fname1, false);
6588         if (!NT_STATUS_IS_OK(status)) {
6589                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6590                 correct = False;
6591         } else {
6592                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6593         }
6594
6595         /*--*/
6596         status = cli_close(cli1, fnum1);
6597         if (!NT_STATUS_IS_OK(status)) {
6598                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6599                 return False;
6600         }
6601
6602         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6603         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6604         if (!NT_STATUS_IS_OK(status)) {
6605                 printf("getatr on file %s failed - %s ! \n",
6606                         fname1, nt_errstr(status));
6607                 correct = False;
6608         } else {
6609                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6610                         printf("Renamed file %s has wrong attr 0x%x "
6611                                 "(should be 0x%x)\n",
6612                                 fname1,
6613                                 attr,
6614                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6615                         correct = False;
6616                 } else {
6617                         printf("Renamed file %s has archive bit set\n", fname1);
6618                 }
6619         }
6620
6621         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6622         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6623
6624         if (!torture_close_connection(cli1)) {
6625                 correct = False;
6626         }
6627
6628         return correct;
6629 }
6630
6631 /*
6632   Test rename into a directory with an ACL denying it.
6633  */
6634 static bool run_rename_access(int dummy)
6635 {
6636         static struct cli_state *cli = NULL;
6637         static struct cli_state *posix_cli = NULL;
6638         const char *src = "test.txt";
6639         const char *dname = "dir";
6640         const char *dst = "dir\\test.txt";
6641         const char *dsrc = "test.dir";
6642         const char *ddst = "dir\\test.dir";
6643         uint16_t fnum = (uint16_t)-1;
6644         struct security_descriptor *sd = NULL;
6645         struct security_descriptor *newsd = NULL;
6646         NTSTATUS status;
6647         TALLOC_CTX *frame = NULL;
6648
6649         frame = talloc_stackframe();
6650         printf("starting rename access test\n");
6651
6652         /* Windows connection. */
6653         if (!torture_open_connection(&cli, 0)) {
6654                 goto fail;
6655         }
6656
6657         smbXcli_conn_set_sockopt(cli->conn, sockops);
6658
6659         /* Posix connection. */
6660         if (!torture_open_connection(&posix_cli, 0)) {
6661                 goto fail;
6662         }
6663
6664         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6665
6666         status = torture_setup_unix_extensions(posix_cli);
6667         if (!NT_STATUS_IS_OK(status)) {
6668                 goto fail;
6669         }
6670
6671         /* Start with a clean slate. */
6672         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6673         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6674         cli_rmdir(cli, dsrc);
6675         cli_rmdir(cli, ddst);
6676         cli_rmdir(cli, dname);
6677
6678         /*
6679          * Setup the destination directory with a DENY ACE to
6680          * prevent new files within it.
6681          */
6682         status = cli_ntcreate(cli,
6683                                 dname,
6684                                 0,
6685                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6686                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6687                                         WRITE_OWNER_ACCESS,
6688                                 FILE_ATTRIBUTE_DIRECTORY,
6689                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6690                                 FILE_CREATE,
6691                                 FILE_DIRECTORY_FILE,
6692                                 0,
6693                                 &fnum,
6694                                 NULL);
6695         if (!NT_STATUS_IS_OK(status)) {
6696                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6697                 goto fail;
6698         }
6699
6700         status = cli_query_secdesc(cli,
6701                                 fnum,
6702                                 frame,
6703                                 &sd);
6704         if (!NT_STATUS_IS_OK(status)) {
6705                 printf("cli_query_secdesc failed for %s (%s)\n",
6706                         dname, nt_errstr(status));
6707                 goto fail;
6708         }
6709
6710         newsd = security_descriptor_dacl_create(frame,
6711                                         0,
6712                                         NULL,
6713                                         NULL,
6714                                         SID_WORLD,
6715                                         SEC_ACE_TYPE_ACCESS_DENIED,
6716                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6717                                         0,
6718                                         NULL);
6719         if (newsd == NULL) {
6720                 goto fail;
6721         }
6722         sd->dacl = security_acl_concatenate(frame,
6723                                         newsd->dacl,
6724                                         sd->dacl);
6725         if (sd->dacl == NULL) {
6726                 goto fail;
6727         }
6728         status = cli_set_secdesc(cli, fnum, sd);
6729         if (!NT_STATUS_IS_OK(status)) {
6730                 printf("cli_set_secdesc failed for %s (%s)\n",
6731                         dname, nt_errstr(status));
6732                 goto fail;
6733         }
6734         status = cli_close(cli, fnum);
6735         if (!NT_STATUS_IS_OK(status)) {
6736                 printf("close failed for %s (%s)\n",
6737                         dname, nt_errstr(status));
6738                 goto fail;
6739         }
6740         /* Now go around the back and chmod to 777 via POSIX. */
6741         status = cli_posix_chmod(posix_cli, dname, 0777);
6742         if (!NT_STATUS_IS_OK(status)) {
6743                 printf("cli_posix_chmod failed for %s (%s)\n",
6744                         dname, nt_errstr(status));
6745                 goto fail;
6746         }
6747
6748         /* Check we can't create a file within dname via Windows. */
6749         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6750         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6751                 cli_close(posix_cli, fnum);
6752                 printf("Create of %s should be ACCESS denied, was %s\n",
6753                         dst, nt_errstr(status));
6754                 goto fail;
6755         }
6756
6757         /* Make the sample file/directory. */
6758         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6759         if (!NT_STATUS_IS_OK(status)) {
6760                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6761                 goto fail;
6762         }
6763         status = cli_close(cli, fnum);
6764         if (!NT_STATUS_IS_OK(status)) {
6765                 printf("cli_close failed (%s)\n", nt_errstr(status));
6766                 goto fail;
6767         }
6768
6769         status = cli_mkdir(cli, dsrc);
6770         if (!NT_STATUS_IS_OK(status)) {
6771                 printf("cli_mkdir of %s failed (%s)\n",
6772                         dsrc, nt_errstr(status));
6773                 goto fail;
6774         }
6775
6776         /*
6777          * OK - renames of the new file and directory into the
6778          * dst directory should fail.
6779          */
6780
6781         status = cli_rename(cli, src, dst, false);
6782         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6783                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6784                         src, dst, nt_errstr(status));
6785                 goto fail;
6786         }
6787         status = cli_rename(cli, dsrc, ddst, false);
6788         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6789                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6790                         src, dst, nt_errstr(status));
6791                 goto fail;
6792         }
6793
6794         TALLOC_FREE(frame);
6795         return true;
6796
6797   fail:
6798
6799         if (posix_cli) {
6800                 torture_close_connection(posix_cli);
6801         }
6802
6803         if (cli) {
6804                 if (fnum != (uint16_t)-1) {
6805                         cli_close(cli, fnum);
6806                 }
6807                 cli_unlink(cli, src,
6808                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6809                 cli_unlink(cli, dst,
6810                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6811                 cli_rmdir(cli, dsrc);
6812                 cli_rmdir(cli, ddst);
6813                 cli_rmdir(cli, dname);
6814
6815                 torture_close_connection(cli);
6816         }
6817
6818         TALLOC_FREE(frame);
6819         return false;
6820 }
6821
6822 /*
6823   Test owner rights ACE.
6824  */
6825 static bool run_owner_rights(int dummy)
6826 {
6827         static struct cli_state *cli = NULL;
6828         const char *fname = "owner_rights.txt";
6829         uint16_t fnum = (uint16_t)-1;
6830         struct security_descriptor *sd = NULL;
6831         struct security_descriptor *newsd = NULL;
6832         NTSTATUS status;
6833         TALLOC_CTX *frame = NULL;
6834
6835         frame = talloc_stackframe();
6836         printf("starting owner rights test\n");
6837
6838         /* Windows connection. */
6839         if (!torture_open_connection(&cli, 0)) {
6840                 goto fail;
6841         }
6842
6843         smbXcli_conn_set_sockopt(cli->conn, sockops);
6844
6845         /* Start with a clean slate. */
6846         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6847
6848         /* Create the test file. */
6849         /* Now try and open for read and write-dac. */
6850         status = cli_ntcreate(cli,
6851                                 fname,
6852                                 0,
6853                                 GENERIC_ALL_ACCESS,
6854                                 FILE_ATTRIBUTE_NORMAL,
6855                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6856                                         FILE_SHARE_DELETE,
6857                                 FILE_CREATE,
6858                                 0,
6859                                 0,
6860                                 &fnum,
6861                                 NULL);
6862         if (!NT_STATUS_IS_OK(status)) {
6863                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6864                 goto fail;
6865         }
6866
6867         /* Get the original SD. */
6868         status = cli_query_secdesc(cli,
6869                                 fnum,
6870                                 frame,
6871                                 &sd);
6872         if (!NT_STATUS_IS_OK(status)) {
6873                 printf("cli_query_secdesc failed for %s (%s)\n",
6874                         fname, nt_errstr(status));
6875                 goto fail;
6876         }
6877
6878         /*
6879          * Add an "owner-rights" ACE denying WRITE_DATA,
6880          * and an "owner-rights" ACE allowing READ_DATA.
6881          */
6882
6883         newsd = security_descriptor_dacl_create(frame,
6884                                         0,
6885                                         NULL,
6886                                         NULL,
6887                                         SID_OWNER_RIGHTS,
6888                                         SEC_ACE_TYPE_ACCESS_DENIED,
6889                                         FILE_WRITE_DATA,
6890                                         0,
6891                                         SID_OWNER_RIGHTS,
6892                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6893                                         FILE_READ_DATA,
6894                                         0,
6895                                         NULL);
6896         if (newsd == NULL) {
6897                 goto fail;
6898         }
6899         sd->dacl = security_acl_concatenate(frame,
6900                                         newsd->dacl,
6901                                         sd->dacl);
6902         if (sd->dacl == NULL) {
6903                 goto fail;
6904         }
6905         status = cli_set_secdesc(cli, fnum, sd);
6906         if (!NT_STATUS_IS_OK(status)) {
6907                 printf("cli_set_secdesc failed for %s (%s)\n",
6908                         fname, nt_errstr(status));
6909                 goto fail;
6910         }
6911         status = cli_close(cli, fnum);
6912         if (!NT_STATUS_IS_OK(status)) {
6913                 printf("close failed for %s (%s)\n",
6914                         fname, nt_errstr(status));
6915                 goto fail;
6916         }
6917         fnum = (uint16_t)-1;
6918
6919         /* Try and open for FILE_WRITE_DATA */
6920         status = cli_ntcreate(cli,
6921                                 fname,
6922                                 0,
6923                                 FILE_WRITE_DATA,
6924                                 FILE_ATTRIBUTE_NORMAL,
6925                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6926                                         FILE_SHARE_DELETE,
6927                                 FILE_OPEN,
6928                                 0,
6929                                 0,
6930                                 &fnum,
6931                                 NULL);
6932         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6933                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6934                 goto fail;
6935         }
6936
6937         /* Now try and open for FILE_READ_DATA */
6938         status = cli_ntcreate(cli,
6939                                 fname,
6940                                 0,
6941                                 FILE_READ_DATA,
6942                                 FILE_ATTRIBUTE_NORMAL,
6943                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6944                                         FILE_SHARE_DELETE,
6945                                 FILE_OPEN,
6946                                 0,
6947                                 0,
6948                                 &fnum,
6949                                 NULL);
6950         if (!NT_STATUS_IS_OK(status)) {
6951                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6952                 goto fail;
6953         }
6954
6955         status = cli_close(cli, fnum);
6956         if (!NT_STATUS_IS_OK(status)) {
6957                 printf("close failed for %s (%s)\n",
6958                         fname, nt_errstr(status));
6959                 goto fail;
6960         }
6961
6962         /* Restore clean slate. */
6963         TALLOC_FREE(sd);
6964         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6965
6966         /* Create the test file. */
6967         status = cli_ntcreate(cli,
6968                                 fname,
6969                                 0,
6970                                 GENERIC_ALL_ACCESS,
6971                                 FILE_ATTRIBUTE_NORMAL,
6972                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6973                                         FILE_SHARE_DELETE,
6974                                 FILE_CREATE,
6975                                 0,
6976                                 0,
6977                                 &fnum,
6978                                 NULL);
6979         if (!NT_STATUS_IS_OK(status)) {
6980                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6981                 goto fail;
6982         }
6983
6984         /* Get the original SD. */
6985         status = cli_query_secdesc(cli,
6986                                 fnum,
6987                                 frame,
6988                                 &sd);
6989         if (!NT_STATUS_IS_OK(status)) {
6990                 printf("cli_query_secdesc failed for %s (%s)\n",
6991                         fname, nt_errstr(status));
6992                 goto fail;
6993         }
6994
6995         /*
6996          * Add an "owner-rights ACE denying WRITE_DATA,
6997          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6998          */
6999
7000         newsd = security_descriptor_dacl_create(frame,
7001                                         0,
7002                                         NULL,
7003                                         NULL,
7004                                         SID_OWNER_RIGHTS,
7005                                         SEC_ACE_TYPE_ACCESS_DENIED,
7006                                         FILE_WRITE_DATA,
7007                                         0,
7008                                         SID_OWNER_RIGHTS,
7009                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7010                                         FILE_READ_DATA|FILE_WRITE_DATA,
7011                                         0,
7012                                         NULL);
7013         if (newsd == NULL) {
7014                 goto fail;
7015         }
7016         sd->dacl = security_acl_concatenate(frame,
7017                                         newsd->dacl,
7018                                         sd->dacl);
7019         if (sd->dacl == NULL) {
7020                 goto fail;
7021         }
7022         status = cli_set_secdesc(cli, fnum, sd);
7023         if (!NT_STATUS_IS_OK(status)) {
7024                 printf("cli_set_secdesc failed for %s (%s)\n",
7025                         fname, nt_errstr(status));
7026                 goto fail;
7027         }
7028         status = cli_close(cli, fnum);
7029         if (!NT_STATUS_IS_OK(status)) {
7030                 printf("close failed for %s (%s)\n",
7031                         fname, nt_errstr(status));
7032                 goto fail;
7033         }
7034         fnum = (uint16_t)-1;
7035
7036         /* Try and open for FILE_WRITE_DATA */
7037         status = cli_ntcreate(cli,
7038                                 fname,
7039                                 0,
7040                                 FILE_WRITE_DATA,
7041                                 FILE_ATTRIBUTE_NORMAL,
7042                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7043                                         FILE_SHARE_DELETE,
7044                                 FILE_OPEN,
7045                                 0,
7046                                 0,
7047                                 &fnum,
7048                                 NULL);
7049         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7050                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7051                 goto fail;
7052         }
7053
7054         /* Now try and open for FILE_READ_DATA */
7055         status = cli_ntcreate(cli,
7056                                 fname,
7057                                 0,
7058                                 FILE_READ_DATA,
7059                                 FILE_ATTRIBUTE_NORMAL,
7060                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7061                                         FILE_SHARE_DELETE,
7062                                 FILE_OPEN,
7063                                 0,
7064                                 0,
7065                                 &fnum,
7066                                 NULL);
7067         if (!NT_STATUS_IS_OK(status)) {
7068                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7069                 goto fail;
7070         }
7071
7072         status = cli_close(cli, fnum);
7073         if (!NT_STATUS_IS_OK(status)) {
7074                 printf("close failed for %s (%s)\n",
7075                         fname, nt_errstr(status));
7076                 goto fail;
7077         }
7078
7079         /* Restore clean slate. */
7080         TALLOC_FREE(sd);
7081         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7082
7083
7084         /* Create the test file. */
7085         status = cli_ntcreate(cli,
7086                                 fname,
7087                                 0,
7088                                 GENERIC_ALL_ACCESS,
7089                                 FILE_ATTRIBUTE_NORMAL,
7090                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7091                                         FILE_SHARE_DELETE,
7092                                 FILE_CREATE,
7093                                 0,
7094                                 0,
7095                                 &fnum,
7096                                 NULL);
7097         if (!NT_STATUS_IS_OK(status)) {
7098                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7099                 goto fail;
7100         }
7101
7102         /* Get the original SD. */
7103         status = cli_query_secdesc(cli,
7104                                 fnum,
7105                                 frame,
7106                                 &sd);
7107         if (!NT_STATUS_IS_OK(status)) {
7108                 printf("cli_query_secdesc failed for %s (%s)\n",
7109                         fname, nt_errstr(status));
7110                 goto fail;
7111         }
7112
7113         /*
7114          * Add an "authenticated users" ACE allowing READ_DATA,
7115          * add an "owner-rights" denying READ_DATA,
7116          * and an "authenticated users" ACE allowing WRITE_DATA.
7117          */
7118
7119         newsd = security_descriptor_dacl_create(frame,
7120                                         0,
7121                                         NULL,
7122                                         NULL,
7123                                         SID_NT_AUTHENTICATED_USERS,
7124                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7125                                         FILE_READ_DATA,
7126                                         0,
7127                                         SID_OWNER_RIGHTS,
7128                                         SEC_ACE_TYPE_ACCESS_DENIED,
7129                                         FILE_READ_DATA,
7130                                         0,
7131                                         SID_NT_AUTHENTICATED_USERS,
7132                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7133                                         FILE_WRITE_DATA,
7134                                         0,
7135                                         NULL);
7136         if (newsd == NULL) {
7137                 printf("newsd == NULL\n");
7138                 goto fail;
7139         }
7140         sd->dacl = security_acl_concatenate(frame,
7141                                         newsd->dacl,
7142                                         sd->dacl);
7143         if (sd->dacl == NULL) {
7144                 printf("sd->dacl == NULL\n");
7145                 goto fail;
7146         }
7147         status = cli_set_secdesc(cli, fnum, sd);
7148         if (!NT_STATUS_IS_OK(status)) {
7149                 printf("cli_set_secdesc failed for %s (%s)\n",
7150                         fname, nt_errstr(status));
7151                 goto fail;
7152         }
7153         status = cli_close(cli, fnum);
7154         if (!NT_STATUS_IS_OK(status)) {
7155                 printf("close failed for %s (%s)\n",
7156                         fname, nt_errstr(status));
7157                 goto fail;
7158         }
7159         fnum = (uint16_t)-1;
7160
7161         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7162         status = cli_ntcreate(cli,
7163                                 fname,
7164                                 0,
7165                                 FILE_READ_DATA|FILE_WRITE_DATA,
7166                                 FILE_ATTRIBUTE_NORMAL,
7167                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7168                                         FILE_SHARE_DELETE,
7169                                 FILE_OPEN,
7170                                 0,
7171                                 0,
7172                                 &fnum,
7173                                 NULL);
7174         if (!NT_STATUS_IS_OK(status)) {
7175                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7176                 goto fail;
7177         }
7178
7179         status = cli_close(cli, fnum);
7180         if (!NT_STATUS_IS_OK(status)) {
7181                 printf("close failed for %s (%s)\n",
7182                         fname, nt_errstr(status));
7183                 goto fail;
7184         }
7185
7186         cli_unlink(cli, fname,
7187                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7188
7189         TALLOC_FREE(frame);
7190         return true;
7191
7192   fail:
7193
7194         if (cli) {
7195                 if (fnum != (uint16_t)-1) {
7196                         cli_close(cli, fnum);
7197                 }
7198                 cli_unlink(cli, fname,
7199                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7200                 torture_close_connection(cli);
7201         }
7202
7203         TALLOC_FREE(frame);
7204         return false;
7205 }
7206
7207 /*
7208  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7209  * Note this test only works with a user with SeSecurityPrivilege set.
7210  *
7211  * NB. This is also tested in samba3.base.createx_access
7212  * but this makes it very explicit what we're looking for.
7213  */
7214 static bool run_smb1_system_security(int dummy)
7215 {
7216         static struct cli_state *cli = NULL;
7217         const char *fname = "system_security.txt";
7218         uint16_t fnum = (uint16_t)-1;
7219         NTSTATUS status;
7220         TALLOC_CTX *frame = NULL;
7221
7222         frame = talloc_stackframe();
7223         printf("starting smb1 system security test\n");
7224
7225         /* SMB1 connection - torture_open_connection() forces this. */
7226         if (!torture_open_connection(&cli, 0)) {
7227                 goto fail;
7228         }
7229
7230         smbXcli_conn_set_sockopt(cli->conn, sockops);
7231
7232         /* Start with a clean slate. */
7233         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7234
7235         /* Create the test file. */
7236         status = cli_ntcreate(cli,
7237                                 fname,
7238                                 0,
7239                                 GENERIC_ALL_ACCESS,
7240                                 FILE_ATTRIBUTE_NORMAL,
7241                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7242                                         FILE_SHARE_DELETE,
7243                                 FILE_CREATE,
7244                                 0,
7245                                 0,
7246                                 &fnum,
7247                                 NULL);
7248         if (!NT_STATUS_IS_OK(status)) {
7249                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7250                 goto fail;
7251         }
7252
7253         status = cli_close(cli, fnum);
7254
7255         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7256         /*
7257          * On SMB1 this succeeds - SMB2 it fails,
7258          * see the SMB2-SACL test.
7259          */
7260         status = cli_ntcreate(cli,
7261                                 fname,
7262                                 0,
7263                                 SEC_FLAG_SYSTEM_SECURITY,
7264                                 FILE_ATTRIBUTE_NORMAL,
7265                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7266                                         FILE_SHARE_DELETE,
7267                                 FILE_OPEN,
7268                                 0,
7269                                 0,
7270                                 &fnum,
7271                                 NULL);
7272         if (!NT_STATUS_IS_OK(status)) {
7273                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7274                 goto fail;
7275         }
7276
7277         status = cli_close(cli, fnum);
7278
7279         cli_unlink(cli, fname,
7280                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7281
7282         torture_close_connection(cli);
7283         TALLOC_FREE(frame);
7284         return true;
7285
7286   fail:
7287
7288         if (cli) {
7289                 if (fnum != (uint16_t)-1) {
7290                         cli_close(cli, fnum);
7291                 }
7292                 cli_unlink(cli, fname,
7293                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294                 torture_close_connection(cli);
7295         }
7296
7297         TALLOC_FREE(frame);
7298         return false;
7299 }
7300
7301 static bool run_pipe_number(int dummy)
7302 {
7303         struct cli_state *cli1;
7304         const char *pipe_name = "\\SPOOLSS";
7305         uint16_t fnum;
7306         int num_pipes = 0;
7307         NTSTATUS status;
7308
7309         printf("starting pipenumber test\n");
7310         if (!torture_open_connection(&cli1, 0)) {
7311                 return False;
7312         }
7313
7314         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7315         while(1) {
7316                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7317                                       FILE_ATTRIBUTE_NORMAL,
7318                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7319                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7320                 if (!NT_STATUS_IS_OK(status)) {
7321                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7322                         break;
7323                 }
7324                 num_pipes++;
7325                 printf("\r%6d", num_pipes);
7326         }
7327
7328         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7329         torture_close_connection(cli1);
7330         return True;
7331 }
7332
7333 /*
7334   Test open mode returns on read-only files.
7335  */
7336 static bool run_opentest(int dummy)
7337 {
7338         static struct cli_state *cli1;
7339         static struct cli_state *cli2;
7340         const char *fname = "\\readonly.file";
7341         uint16_t fnum1, fnum2;
7342         char buf[20];
7343         off_t fsize;
7344         bool correct = True;
7345         char *tmp_path;
7346         NTSTATUS status;
7347
7348         printf("starting open test\n");
7349
7350         if (!torture_open_connection(&cli1, 0)) {
7351                 return False;
7352         }
7353
7354         cli_setatr(cli1, fname, 0, 0);
7355         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7356
7357         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7358
7359         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7360         if (!NT_STATUS_IS_OK(status)) {
7361                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7362                 return False;
7363         }
7364
7365         status = cli_close(cli1, fnum1);
7366         if (!NT_STATUS_IS_OK(status)) {
7367                 printf("close2 failed (%s)\n", nt_errstr(status));
7368                 return False;
7369         }
7370
7371         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7372         if (!NT_STATUS_IS_OK(status)) {
7373                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7374                 return False;
7375         }
7376
7377         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7378         if (!NT_STATUS_IS_OK(status)) {
7379                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7380                 return False;
7381         }
7382
7383         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7384         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7385
7386         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7387                         NT_STATUS_ACCESS_DENIED)) {
7388                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7389         }
7390
7391         printf("finished open test 1\n");
7392
7393         cli_close(cli1, fnum1);
7394
7395         /* Now try not readonly and ensure ERRbadshare is returned. */
7396
7397         cli_setatr(cli1, fname, 0, 0);
7398
7399         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7400         if (!NT_STATUS_IS_OK(status)) {
7401                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7402                 return False;
7403         }
7404
7405         /* This will fail - but the error should be ERRshare. */
7406         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7407
7408         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7409                         NT_STATUS_SHARING_VIOLATION)) {
7410                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7411         }
7412
7413         status = cli_close(cli1, fnum1);
7414         if (!NT_STATUS_IS_OK(status)) {
7415                 printf("close2 failed (%s)\n", nt_errstr(status));
7416                 return False;
7417         }
7418
7419         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7420
7421         printf("finished open test 2\n");
7422
7423         /* Test truncate open disposition on file opened for read. */
7424         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7425         if (!NT_STATUS_IS_OK(status)) {
7426                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7427                 return False;
7428         }
7429
7430         /* write 20 bytes. */
7431
7432         memset(buf, '\0', 20);
7433
7434         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7435         if (!NT_STATUS_IS_OK(status)) {
7436                 printf("write failed (%s)\n", nt_errstr(status));
7437                 correct = False;
7438         }
7439
7440         status = cli_close(cli1, fnum1);
7441         if (!NT_STATUS_IS_OK(status)) {
7442                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7443                 return False;
7444         }
7445
7446         /* Ensure size == 20. */
7447         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7448         if (!NT_STATUS_IS_OK(status)) {
7449                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7450                 return False;
7451         }
7452
7453         if (fsize != 20) {
7454                 printf("(3) file size != 20\n");
7455                 return False;
7456         }
7457
7458         /* Now test if we can truncate a file opened for readonly. */
7459         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7460         if (!NT_STATUS_IS_OK(status)) {
7461                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7462                 return False;
7463         }
7464
7465         status = cli_close(cli1, fnum1);
7466         if (!NT_STATUS_IS_OK(status)) {
7467                 printf("close2 failed (%s)\n", nt_errstr(status));
7468                 return False;
7469         }
7470
7471         /* Ensure size == 0. */
7472         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7473         if (!NT_STATUS_IS_OK(status)) {
7474                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7475                 return False;
7476         }
7477
7478         if (fsize != 0) {
7479                 printf("(3) file size != 0\n");
7480                 return False;
7481         }
7482         printf("finished open test 3\n");
7483
7484         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7485
7486         printf("Do ctemp tests\n");
7487         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7488         if (!NT_STATUS_IS_OK(status)) {
7489                 printf("ctemp failed (%s)\n", nt_errstr(status));
7490                 return False;
7491         }
7492
7493         printf("ctemp gave path %s\n", tmp_path);
7494         status = cli_close(cli1, fnum1);
7495         if (!NT_STATUS_IS_OK(status)) {
7496                 printf("close of temp failed (%s)\n", nt_errstr(status));
7497         }
7498
7499         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7500         if (!NT_STATUS_IS_OK(status)) {
7501                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7502         }
7503
7504         /* Test the non-io opens... */
7505
7506         if (!torture_open_connection(&cli2, 1)) {
7507                 return False;
7508         }
7509
7510         cli_setatr(cli2, fname, 0, 0);
7511         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7512
7513         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7514
7515         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7516         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7517                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7518                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7519         if (!NT_STATUS_IS_OK(status)) {
7520                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7521                 return False;
7522         }
7523
7524         status = cli_ntcreate(cli2, fname, 0, 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 #1 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 #1 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 #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7541                 return False;
7542         }
7543
7544         printf("non-io open test #1 passed.\n");
7545
7546         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7547
7548         printf("TEST #2 testing 2 non-io opens (first 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 #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7556                 return False;
7557         }
7558
7559         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7560                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7561                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7562         if (!NT_STATUS_IS_OK(status)) {
7563                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7564                 return False;
7565         }
7566
7567         status = cli_close(cli1, fnum1);
7568         if (!NT_STATUS_IS_OK(status)) {
7569                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7570                 return False;
7571         }
7572
7573         status = cli_close(cli2, fnum2);
7574         if (!NT_STATUS_IS_OK(status)) {
7575                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7576                 return False;
7577         }
7578
7579         printf("non-io open test #2 passed.\n");
7580
7581         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7582
7583         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7584
7585         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7586                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7587                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7588         if (!NT_STATUS_IS_OK(status)) {
7589                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7590                 return False;
7591         }
7592
7593         status = cli_ntcreate(cli2, fname, 0,
7594                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7595                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7596                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7597         if (!NT_STATUS_IS_OK(status)) {
7598                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7599                 return False;
7600         }
7601
7602         status = cli_close(cli1, fnum1);
7603         if (!NT_STATUS_IS_OK(status)) {
7604                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7605                 return False;
7606         }
7607
7608         status = cli_close(cli2, fnum2);
7609         if (!NT_STATUS_IS_OK(status)) {
7610                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7611                 return False;
7612         }
7613
7614         printf("non-io open test #3 passed.\n");
7615
7616         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7617
7618         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7619
7620         status = cli_ntcreate(cli1, fname, 0,
7621                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7622                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7623                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7624         if (!NT_STATUS_IS_OK(status)) {
7625                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7626                 return False;
7627         }
7628
7629         status = cli_ntcreate(cli2, fname, 0,
7630                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7631                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7632                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7633         if (NT_STATUS_IS_OK(status)) {
7634                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7635                 return False;
7636         }
7637
7638         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7639
7640         status = cli_close(cli1, fnum1);
7641         if (!NT_STATUS_IS_OK(status)) {
7642                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7643                 return False;
7644         }
7645
7646         printf("non-io open test #4 passed.\n");
7647
7648         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7649
7650         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7651
7652         status = cli_ntcreate(cli1, fname, 0,
7653                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7654                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7655                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7656         if (!NT_STATUS_IS_OK(status)) {
7657                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7658                 return False;
7659         }
7660
7661         status = cli_ntcreate(cli2, fname, 0,
7662                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7663                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7664                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7665         if (!NT_STATUS_IS_OK(status)) {
7666                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7667                 return False;
7668         }
7669
7670         status = cli_close(cli1, fnum1);
7671         if (!NT_STATUS_IS_OK(status)) {
7672                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7673                 return False;
7674         }
7675
7676         status = cli_close(cli2, fnum2);
7677         if (!NT_STATUS_IS_OK(status)) {
7678                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7679                 return False;
7680         }
7681
7682         printf("non-io open test #5 passed.\n");
7683
7684         printf("TEST #6 testing 1 non-io open, one io open\n");
7685
7686         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7687
7688         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7689                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7690                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7691         if (!NT_STATUS_IS_OK(status)) {
7692                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7693                 return False;
7694         }
7695
7696         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7697                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7698                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7699         if (!NT_STATUS_IS_OK(status)) {
7700                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7701                 return False;
7702         }
7703
7704         status = cli_close(cli1, fnum1);
7705         if (!NT_STATUS_IS_OK(status)) {
7706                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7707                 return False;
7708         }
7709
7710         status = cli_close(cli2, fnum2);
7711         if (!NT_STATUS_IS_OK(status)) {
7712                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7713                 return False;
7714         }
7715
7716         printf("non-io open test #6 passed.\n");
7717
7718         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7719
7720         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7721
7722         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7723                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7724                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7725         if (!NT_STATUS_IS_OK(status)) {
7726                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7727                 return False;
7728         }
7729
7730         status = cli_ntcreate(cli2, fname, 0,
7731                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7732                               FILE_ATTRIBUTE_NORMAL,
7733                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7734                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7735         if (NT_STATUS_IS_OK(status)) {
7736                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7737                 return False;
7738         }
7739
7740         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7741
7742         status = cli_close(cli1, fnum1);
7743         if (!NT_STATUS_IS_OK(status)) {
7744                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7745                 return False;
7746         }
7747
7748         printf("non-io open test #7 passed.\n");
7749
7750         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7751
7752         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7753         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7754                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7755                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7756         if (!NT_STATUS_IS_OK(status)) {
7757                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7758                 correct = false;
7759                 goto out;
7760         }
7761
7762         /* Write to ensure we have to update the file time. */
7763         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7764                               NULL);
7765         if (!NT_STATUS_IS_OK(status)) {
7766                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7767                 correct = false;
7768                 goto out;
7769         }
7770
7771         status = cli_close(cli1, fnum1);
7772         if (!NT_STATUS_IS_OK(status)) {
7773                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7774                 correct = false;
7775         }
7776
7777   out:
7778
7779         if (!torture_close_connection(cli1)) {
7780                 correct = False;
7781         }
7782         if (!torture_close_connection(cli2)) {
7783                 correct = False;
7784         }
7785
7786         return correct;
7787 }
7788
7789 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7790 {
7791         uint16_t major, minor;
7792         uint32_t caplow, caphigh;
7793         NTSTATUS status;
7794
7795         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7796                 printf("Server doesn't support UNIX CIFS extensions.\n");
7797                 return NT_STATUS_NOT_SUPPORTED;
7798         }
7799
7800         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7801                                              &caphigh);
7802         if (!NT_STATUS_IS_OK(status)) {
7803                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7804                        nt_errstr(status));
7805                 return status;
7806         }
7807
7808         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7809                                                       caplow, caphigh);
7810         if (!NT_STATUS_IS_OK(status)) {
7811                 printf("Server doesn't support setting UNIX CIFS extensions: "
7812                        "%s.\n", nt_errstr(status));
7813                 return status;
7814         }
7815
7816         return NT_STATUS_OK;
7817 }
7818
7819 /*
7820   Test POSIX open /mkdir calls.
7821  */
7822 static bool run_simple_posix_open_test(int dummy)
7823 {
7824         static struct cli_state *cli1;
7825         const char *fname = "posix:file";
7826         const char *hname = "posix:hlink";
7827         const char *sname = "posix:symlink";
7828         const char *dname = "posix:dir";
7829         char buf[10];
7830         char *target = NULL;
7831         uint16_t fnum1 = (uint16_t)-1;
7832         SMB_STRUCT_STAT sbuf;
7833         bool correct = false;
7834         NTSTATUS status;
7835         size_t nread;
7836         const char *fname_windows = "windows_file";
7837         uint16_t fnum2 = (uint16_t)-1;
7838         bool ok;
7839
7840         printf("Starting simple POSIX open test\n");
7841
7842         if (!torture_open_connection(&cli1, 0)) {
7843                 return false;
7844         }
7845
7846         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7847
7848         status = torture_setup_unix_extensions(cli1);
7849         if (!NT_STATUS_IS_OK(status)) {
7850                 return false;
7851         }
7852
7853         cli_setatr(cli1, fname, 0, 0);
7854         cli_posix_unlink(cli1, fname);
7855         cli_setatr(cli1, dname, 0, 0);
7856         cli_posix_rmdir(cli1, dname);
7857         cli_setatr(cli1, hname, 0, 0);
7858         cli_posix_unlink(cli1, hname);
7859         cli_setatr(cli1, sname, 0, 0);
7860         cli_posix_unlink(cli1, sname);
7861         cli_setatr(cli1, fname_windows, 0, 0);
7862         cli_posix_unlink(cli1, fname_windows);
7863
7864         /* Create a directory. */
7865         status = cli_posix_mkdir(cli1, dname, 0777);
7866         if (!NT_STATUS_IS_OK(status)) {
7867                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7868                 goto out;
7869         }
7870
7871         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7872                                 0600, &fnum1);
7873         if (!NT_STATUS_IS_OK(status)) {
7874                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7875                 goto out;
7876         }
7877
7878         /* Test ftruncate - set file size. */
7879         status = cli_ftruncate(cli1, fnum1, 1000);
7880         if (!NT_STATUS_IS_OK(status)) {
7881                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7882                 goto out;
7883         }
7884
7885         /* Ensure st_size == 1000 */
7886         status = cli_posix_stat(cli1, fname, &sbuf);
7887         if (!NT_STATUS_IS_OK(status)) {
7888                 printf("stat failed (%s)\n", nt_errstr(status));
7889                 goto out;
7890         }
7891
7892         if (sbuf.st_ex_size != 1000) {
7893                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7894                 goto out;
7895         }
7896
7897         /* Ensure st_mode == 0600 */
7898         if ((sbuf.st_ex_mode & 07777) != 0600) {
7899                 printf("posix_open - bad permissions 0%o != 0600\n",
7900                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7901                 goto out;
7902         }
7903
7904         /* Test ftruncate - set file size back to zero. */
7905         status = cli_ftruncate(cli1, fnum1, 0);
7906         if (!NT_STATUS_IS_OK(status)) {
7907                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7908                 goto out;
7909         }
7910
7911         status = cli_close(cli1, fnum1);
7912         if (!NT_STATUS_IS_OK(status)) {
7913                 printf("close failed (%s)\n", nt_errstr(status));
7914                 goto out;
7915         }
7916
7917         /* Now open the file again for read only. */
7918         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7919         if (!NT_STATUS_IS_OK(status)) {
7920                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7921                 goto out;
7922         }
7923
7924         /* Now unlink while open. */
7925         status = cli_posix_unlink(cli1, fname);
7926         if (!NT_STATUS_IS_OK(status)) {
7927                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7928                 goto out;
7929         }
7930
7931         status = cli_close(cli1, fnum1);
7932         if (!NT_STATUS_IS_OK(status)) {
7933                 printf("close(2) failed (%s)\n", nt_errstr(status));
7934                 goto out;
7935         }
7936
7937         /* Ensure the file has gone. */
7938         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7939         if (NT_STATUS_IS_OK(status)) {
7940                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7941                 goto out;
7942         }
7943
7944         /* Create again to test open with O_TRUNC. */
7945         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7946         if (!NT_STATUS_IS_OK(status)) {
7947                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7948                 goto out;
7949         }
7950
7951         /* Test ftruncate - set file size. */
7952         status = cli_ftruncate(cli1, fnum1, 1000);
7953         if (!NT_STATUS_IS_OK(status)) {
7954                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7955                 goto out;
7956         }
7957
7958         /* Ensure st_size == 1000 */
7959         status = cli_posix_stat(cli1, fname, &sbuf);
7960         if (!NT_STATUS_IS_OK(status)) {
7961                 printf("stat failed (%s)\n", nt_errstr(status));
7962                 goto out;
7963         }
7964
7965         if (sbuf.st_ex_size != 1000) {
7966                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7967                 goto out;
7968         }
7969
7970         status = cli_close(cli1, fnum1);
7971         if (!NT_STATUS_IS_OK(status)) {
7972                 printf("close(2) failed (%s)\n", nt_errstr(status));
7973                 goto out;
7974         }
7975
7976         /* Re-open with O_TRUNC. */
7977         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7978         if (!NT_STATUS_IS_OK(status)) {
7979                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7980                 goto out;
7981         }
7982
7983         /* Ensure st_size == 0 */
7984         status = cli_posix_stat(cli1, fname, &sbuf);
7985         if (!NT_STATUS_IS_OK(status)) {
7986                 printf("stat failed (%s)\n", nt_errstr(status));
7987                 goto out;
7988         }
7989
7990         if (sbuf.st_ex_size != 0) {
7991                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7992                 goto out;
7993         }
7994
7995         status = cli_close(cli1, fnum1);
7996         if (!NT_STATUS_IS_OK(status)) {
7997                 printf("close failed (%s)\n", nt_errstr(status));
7998                 goto out;
7999         }
8000
8001         status = cli_posix_unlink(cli1, fname);
8002         if (!NT_STATUS_IS_OK(status)) {
8003                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8004                 goto out;
8005         }
8006
8007         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8008         if (!NT_STATUS_IS_OK(status)) {
8009                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8010                         dname, nt_errstr(status));
8011                 goto out;
8012         }
8013
8014         cli_close(cli1, fnum1);
8015
8016         /* What happens when we try and POSIX open a directory for write ? */
8017         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8018         if (NT_STATUS_IS_OK(status)) {
8019                 printf("POSIX open of directory %s succeeded, "
8020                        "should have failed.\n",
8021                        dname);
8022                 goto out;
8023         } else {
8024                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8025                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8026                         goto out;
8027                 }
8028         }
8029
8030         /* Create the file. */
8031         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8032                                 0600, &fnum1);
8033         if (!NT_STATUS_IS_OK(status)) {
8034                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8035                 goto out;
8036         }
8037
8038         /* Write some data into it. */
8039         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8040                               NULL);
8041         if (!NT_STATUS_IS_OK(status)) {
8042                 printf("cli_write failed: %s\n", nt_errstr(status));
8043                 goto out;
8044         }
8045
8046         cli_close(cli1, fnum1);
8047
8048         /* Now create a hardlink. */
8049         status = cli_posix_hardlink(cli1, fname, hname);
8050         if (!NT_STATUS_IS_OK(status)) {
8051                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8052                 goto out;
8053         }
8054
8055         /* Now create a symlink. */
8056         status = cli_posix_symlink(cli1, fname, sname);
8057         if (!NT_STATUS_IS_OK(status)) {
8058                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8059                 goto out;
8060         }
8061
8062         /* Open the hardlink for read. */
8063         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8064         if (!NT_STATUS_IS_OK(status)) {
8065                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8066                 goto out;
8067         }
8068
8069         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8070         if (!NT_STATUS_IS_OK(status)) {
8071                 printf("POSIX read of %s failed (%s)\n", hname,
8072                        nt_errstr(status));
8073                 goto out;
8074         } else if (nread != 10) {
8075                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8076                        hname, (unsigned long)nread, 10);
8077                 goto out;
8078         }
8079
8080         if (memcmp(buf, "TEST DATA\n", 10)) {
8081                 printf("invalid data read from hardlink\n");
8082                 goto out;
8083         }
8084
8085         /* Do a POSIX lock/unlock. */
8086         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8087         if (!NT_STATUS_IS_OK(status)) {
8088                 printf("POSIX lock failed %s\n", nt_errstr(status));
8089                 goto out;
8090         }
8091
8092         /* Punch a hole in the locked area. */
8093         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8094         if (!NT_STATUS_IS_OK(status)) {
8095                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8096                 goto out;
8097         }
8098
8099         cli_close(cli1, fnum1);
8100
8101         /* Open the symlink for read - this should fail. A POSIX
8102            client should not be doing opens on a symlink. */
8103         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8104         if (NT_STATUS_IS_OK(status)) {
8105                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8106                 goto out;
8107         }
8108         ok = check_both_error(
8109                 __LINE__, status, ERRDOS, ERRbadpath,
8110                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8111         if (!ok) {
8112                 printf("POSIX open of %s should have failed "
8113                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8114                        "failed with %s instead.\n",
8115                        sname, nt_errstr(status));
8116                 goto out;
8117         }
8118
8119         status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8120         if (!NT_STATUS_IS_OK(status)) {
8121                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8122                 goto out;
8123         }
8124
8125         if (strcmp(target, fname) != 0) {
8126                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8127                         sname, fname, target);
8128                 goto out;
8129         }
8130
8131         status = cli_posix_rmdir(cli1, dname);
8132         if (!NT_STATUS_IS_OK(status)) {
8133                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8134                 goto out;
8135         }
8136
8137         /* Check directory opens with a specific permission. */
8138         status = cli_posix_mkdir(cli1, dname, 0700);
8139         if (!NT_STATUS_IS_OK(status)) {
8140                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8141                 goto out;
8142         }
8143
8144         /* Ensure st_mode == 0700 */
8145         status = cli_posix_stat(cli1, dname, &sbuf);
8146         if (!NT_STATUS_IS_OK(status)) {
8147                 printf("stat failed (%s)\n", nt_errstr(status));
8148                 goto out;
8149         }
8150
8151         if ((sbuf.st_ex_mode & 07777) != 0700) {
8152                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8153                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8154                 goto out;
8155         }
8156
8157         /*
8158          * Now create a Windows file, and attempt a POSIX unlink.
8159          * This should fail with a sharing violation but due to:
8160          *
8161          * [Bug 9571] Unlink after open causes smbd to panic
8162          *
8163          * ensure we've fixed the lock ordering violation.
8164          */
8165
8166         status = cli_ntcreate(cli1, fname_windows, 0,
8167                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8168                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8169                         FILE_CREATE,
8170                         0x0, 0x0, &fnum2, NULL);
8171         if (!NT_STATUS_IS_OK(status)) {
8172                 printf("Windows create of %s failed (%s)\n", fname_windows,
8173                         nt_errstr(status));
8174                 goto out;
8175         }
8176
8177         /* Now try posix_unlink. */
8178         status = cli_posix_unlink(cli1, fname_windows);
8179         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8180                 printf("POSIX unlink of %s should fail "
8181                         "with NT_STATUS_SHARING_VIOLATION "
8182                         "got %s instead !\n",
8183                         fname_windows,
8184                         nt_errstr(status));
8185                 goto out;
8186         }
8187
8188         cli_close(cli1, fnum2);
8189
8190         printf("Simple POSIX open test passed\n");
8191         correct = true;
8192
8193   out:
8194
8195         if (fnum1 != (uint16_t)-1) {
8196                 cli_close(cli1, fnum1);
8197                 fnum1 = (uint16_t)-1;
8198         }
8199
8200         if (fnum2 != (uint16_t)-1) {
8201                 cli_close(cli1, fnum2);
8202                 fnum2 = (uint16_t)-1;
8203         }
8204
8205         cli_setatr(cli1, sname, 0, 0);
8206         cli_posix_unlink(cli1, sname);
8207         cli_setatr(cli1, hname, 0, 0);
8208         cli_posix_unlink(cli1, hname);
8209         cli_setatr(cli1, fname, 0, 0);
8210         cli_posix_unlink(cli1, fname);
8211         cli_setatr(cli1, dname, 0, 0);
8212         cli_posix_rmdir(cli1, dname);
8213         cli_setatr(cli1, fname_windows, 0, 0);
8214         cli_posix_unlink(cli1, fname_windows);
8215
8216         if (!torture_close_connection(cli1)) {
8217                 correct = false;
8218         }
8219
8220         return correct;
8221 }
8222
8223 /*
8224   Test POSIX and Windows ACLs are rejected on symlinks.
8225  */
8226 static bool run_acl_symlink_test(int dummy)
8227 {
8228         static struct cli_state *cli;
8229         const char *fname = "posix_file";
8230         const char *sname = "posix_symlink";
8231         uint16_t fnum = (uint16_t)-1;
8232         bool correct = false;
8233         NTSTATUS status;
8234         char *posix_acl = NULL;
8235         size_t posix_acl_len = 0;
8236         char *posix_acl_sym = NULL;
8237         size_t posix_acl_len_sym = 0;
8238         struct security_descriptor *sd = NULL;
8239         TALLOC_CTX *frame = NULL;
8240
8241         frame = talloc_stackframe();
8242
8243         printf("Starting acl symlink test\n");
8244
8245         if (!torture_open_connection(&cli, 0)) {
8246                 TALLOC_FREE(frame);
8247                 return false;
8248         }
8249
8250         smbXcli_conn_set_sockopt(cli->conn, sockops);
8251
8252         status = torture_setup_unix_extensions(cli);
8253         if (!NT_STATUS_IS_OK(status)) {
8254                 TALLOC_FREE(frame);
8255                 return false;
8256         }
8257
8258         cli_setatr(cli, fname, 0, 0);
8259         cli_posix_unlink(cli, fname);
8260         cli_setatr(cli, sname, 0, 0);
8261         cli_posix_unlink(cli, sname);
8262
8263         status = cli_ntcreate(cli,
8264                         fname,
8265                         0,
8266                         READ_CONTROL_ACCESS,
8267                         0,
8268                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8269                         FILE_CREATE,
8270                         0x0,
8271                         0x0,
8272                         &fnum,
8273                         NULL);
8274
8275         if (!NT_STATUS_IS_OK(status)) {
8276                 printf("cli_ntcreate of %s failed (%s)\n",
8277                         fname,
8278                         nt_errstr(status));
8279                 goto out;
8280         }
8281
8282         /* Get the Windows ACL on the file. */
8283         status = cli_query_secdesc(cli,
8284                                 fnum,
8285                                 frame,
8286                                 &sd);
8287         if (!NT_STATUS_IS_OK(status)) {
8288                 printf("cli_query_secdesc failed (%s)\n",
8289                         nt_errstr(status));
8290                 goto out;
8291         }
8292
8293         /* Get the POSIX ACL on the file. */
8294         status = cli_posix_getacl(cli,
8295                                 fname,
8296                                 frame,
8297                                 &posix_acl_len,
8298                                 &posix_acl);
8299
8300         if (!NT_STATUS_IS_OK(status)) {
8301                 printf("cli_posix_getacl failed (%s)\n",
8302                         nt_errstr(status));
8303                 goto out;
8304         }
8305
8306         status = cli_close(cli, fnum);
8307         if (!NT_STATUS_IS_OK(status)) {
8308                 printf("close failed (%s)\n", nt_errstr(status));
8309                 goto out;
8310         }
8311         fnum = (uint16_t)-1;
8312
8313         /* Now create a symlink. */
8314         status = cli_posix_symlink(cli, fname, sname);
8315         if (!NT_STATUS_IS_OK(status)) {
8316                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8317                         sname,
8318                         fname,
8319                         nt_errstr(status));
8320                 goto out;
8321         }
8322
8323         /* Open a handle on the symlink for SD set/get should fail. */
8324         status = cli_ntcreate(cli,
8325                         sname,
8326                         0,
8327                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8328                         0,
8329                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8330                         FILE_OPEN,
8331                         0x0,
8332                         0x0,
8333                         &fnum,
8334                         NULL);
8335
8336         if (NT_STATUS_IS_OK(status)) {
8337                 printf("Symlink open for getsd/setsd of %s "
8338                         "succeeded (should fail)\n",
8339                         sname);
8340                 goto out;
8341         }
8342
8343         /* Try a stat-open on the symlink, should also fail. */
8344         status = cli_ntcreate(cli,
8345                         sname,
8346                         0,
8347                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8348                         0,
8349                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8350                         FILE_OPEN,
8351                         0x0,
8352                         0x0,
8353                         &fnum,
8354                         NULL);
8355
8356         if (NT_STATUS_IS_OK(status)) {
8357                 printf("Stat-open of symlink succeeded (should fail)\n");
8358                 goto out;
8359         }
8360
8361         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8362         status = cli_posix_getacl(cli,
8363                                 sname,
8364                                 frame,
8365                                 &posix_acl_len_sym,
8366                                 &posix_acl_sym);
8367
8368         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8369                 printf("cli_posix_getacl on a symlink gave %s. "
8370                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8371                         nt_errstr(status));
8372                 goto out;
8373         }
8374
8375         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8376         status = cli_posix_setacl(cli,
8377                                 sname,
8378                                 posix_acl,
8379                                 posix_acl_len);
8380
8381         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8382                 printf("cli_posix_setacl on a symlink gave %s. "
8383                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8384                         nt_errstr(status));
8385                 goto out;
8386         }
8387
8388         printf("ACL symlink test passed\n");
8389         correct = true;
8390
8391   out:
8392
8393         if (fnum != (uint16_t)-1) {
8394                 cli_close(cli, fnum);
8395                 fnum = (uint16_t)-1;
8396         }
8397
8398         cli_setatr(cli, sname, 0, 0);
8399         cli_posix_unlink(cli, sname);
8400         cli_setatr(cli, fname, 0, 0);
8401         cli_posix_unlink(cli, fname);
8402
8403         if (!torture_close_connection(cli)) {
8404                 correct = false;
8405         }
8406
8407         TALLOC_FREE(frame);
8408         return correct;
8409 }
8410
8411 /*
8412   Test POSIX can delete a file containing streams.
8413  */
8414 static bool run_posix_stream_delete(int dummy)
8415 {
8416         struct cli_state *cli1 = NULL;
8417         struct cli_state *cli2 = NULL;
8418         const char *fname = "streamfile";
8419         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8420         uint16_t fnum1 = (uint16_t)-1;
8421         bool correct = false;
8422         NTSTATUS status;
8423         TALLOC_CTX *frame = NULL;
8424
8425         frame = talloc_stackframe();
8426
8427         printf("Starting POSIX stream delete test\n");
8428
8429         if (!torture_open_connection(&cli1, 0) ||
8430                         !torture_open_connection(&cli2, 1)) {
8431                 TALLOC_FREE(frame);
8432                 return false;
8433         }
8434
8435         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8436         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8437
8438         status = torture_setup_unix_extensions(cli2);
8439         if (!NT_STATUS_IS_OK(status)) {
8440                 goto out;
8441         }
8442
8443         cli_setatr(cli1, fname, 0, 0);
8444         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8445
8446         /* Create the file. */
8447         status = cli_ntcreate(cli1,
8448                         fname,
8449                         0,
8450                         READ_CONTROL_ACCESS,
8451                         0,
8452                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8453                         FILE_CREATE,
8454                         0x0,
8455                         0x0,
8456                         &fnum1,
8457                         NULL);
8458
8459         if (!NT_STATUS_IS_OK(status)) {
8460                 printf("cli_ntcreate of %s failed (%s)\n",
8461                         fname,
8462                         nt_errstr(status));
8463                 goto out;
8464         }
8465
8466         status = cli_close(cli1, fnum1);
8467         if (!NT_STATUS_IS_OK(status)) {
8468                 printf("cli_close of %s failed (%s)\n",
8469                         fname,
8470                         nt_errstr(status));
8471                 goto out;
8472         }
8473         fnum1 = (uint16_t)-1;
8474
8475         /* Now create the stream. */
8476         status = cli_ntcreate(cli1,
8477                         stream_fname,
8478                         0,
8479                         FILE_WRITE_DATA,
8480                         0,
8481                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8482                         FILE_CREATE,
8483                         0x0,
8484                         0x0,
8485                         &fnum1,
8486                         NULL);
8487
8488         if (!NT_STATUS_IS_OK(status)) {
8489                 printf("cli_ntcreate of %s failed (%s)\n",
8490                         stream_fname,
8491                         nt_errstr(status));
8492                 goto out;
8493         }
8494
8495         /* Leave the stream handle open... */
8496
8497         /* POSIX unlink should fail. */
8498         status = cli_posix_unlink(cli2, fname);
8499         if (NT_STATUS_IS_OK(status)) {
8500                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8501                         fname);
8502                 goto out;
8503         }
8504
8505         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8506                 printf("cli_posix_unlink of %s failed with (%s) "
8507                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8508                         fname,
8509                         nt_errstr(status));
8510                 goto out;
8511         }
8512
8513         /* Close the stream handle. */
8514         status = cli_close(cli1, fnum1);
8515         if (!NT_STATUS_IS_OK(status)) {
8516                 printf("cli_close of %s failed (%s)\n",
8517                         stream_fname,
8518                         nt_errstr(status));
8519                 goto out;
8520         }
8521         fnum1 = (uint16_t)-1;
8522
8523         /* POSIX unlink after stream handle closed should succeed. */
8524         status = cli_posix_unlink(cli2, fname);
8525         if (!NT_STATUS_IS_OK(status)) {
8526                 printf("cli_posix_unlink of %s failed (%s)\n",
8527                         fname,
8528                         nt_errstr(status));
8529                 goto out;
8530         }
8531
8532         printf("POSIX stream delete test passed\n");
8533         correct = true;
8534
8535   out:
8536
8537         if (fnum1 != (uint16_t)-1) {
8538                 cli_close(cli1, fnum1);
8539                 fnum1 = (uint16_t)-1;
8540         }
8541
8542         cli_setatr(cli1, fname, 0, 0);
8543         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8544
8545         if (!torture_close_connection(cli1)) {
8546                 correct = false;
8547         }
8548         if (!torture_close_connection(cli2)) {
8549                 correct = false;
8550         }
8551
8552         TALLOC_FREE(frame);
8553         return correct;
8554 }
8555
8556 /*
8557   Test setting EA's are rejected on symlinks.
8558  */
8559 static bool run_ea_symlink_test(int dummy)
8560 {
8561         static struct cli_state *cli;
8562         const char *fname = "posix_file_ea";
8563         const char *sname = "posix_symlink_ea";
8564         const char *ea_name = "testea_name";
8565         const char *ea_value = "testea_value";
8566         uint16_t fnum = (uint16_t)-1;
8567         bool correct = false;
8568         NTSTATUS status;
8569         size_t i, num_eas;
8570         struct ea_struct *eas = NULL;
8571         TALLOC_CTX *frame = NULL;
8572
8573         frame = talloc_stackframe();
8574
8575         printf("Starting EA symlink test\n");
8576
8577         if (!torture_open_connection(&cli, 0)) {
8578                 TALLOC_FREE(frame);
8579                 return false;
8580         }
8581
8582         smbXcli_conn_set_sockopt(cli->conn, sockops);
8583
8584         status = torture_setup_unix_extensions(cli);
8585         if (!NT_STATUS_IS_OK(status)) {
8586                 TALLOC_FREE(frame);
8587                 return false;
8588         }
8589
8590         cli_setatr(cli, fname, 0, 0);
8591         cli_posix_unlink(cli, fname);
8592         cli_setatr(cli, sname, 0, 0);
8593         cli_posix_unlink(cli, sname);
8594
8595         status = cli_ntcreate(cli,
8596                         fname,
8597                         0,
8598                         READ_CONTROL_ACCESS,
8599                         0,
8600                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8601                         FILE_CREATE,
8602                         0x0,
8603                         0x0,
8604                         &fnum,
8605                         NULL);
8606
8607         if (!NT_STATUS_IS_OK(status)) {
8608                 printf("cli_ntcreate of %s failed (%s)\n",
8609                         fname,
8610                         nt_errstr(status));
8611                 goto out;
8612         }
8613
8614         status = cli_close(cli, fnum);
8615         if (!NT_STATUS_IS_OK(status)) {
8616                 printf("close failed (%s)\n",
8617                         nt_errstr(status));
8618                 goto out;
8619         }
8620         fnum = (uint16_t)-1;
8621
8622         /* Set an EA on the path. */
8623         status = cli_set_ea_path(cli,
8624                                 fname,
8625                                 ea_name,
8626                                 ea_value,
8627                                 strlen(ea_value)+1);
8628
8629         if (!NT_STATUS_IS_OK(status)) {
8630                 printf("cli_set_ea_path failed (%s)\n",
8631                         nt_errstr(status));
8632                 goto out;
8633         }
8634
8635         /* Now create a symlink. */
8636         status = cli_posix_symlink(cli, fname, sname);
8637         if (!NT_STATUS_IS_OK(status)) {
8638                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8639                         sname,
8640                         fname,
8641                         nt_errstr(status));
8642                 goto out;
8643         }
8644
8645         /* Get the EA list on the path. Should return value set. */
8646         status = cli_get_ea_list_path(cli,
8647                                 fname,
8648                                 frame,
8649                                 &num_eas,
8650                                 &eas);
8651
8652         if (!NT_STATUS_IS_OK(status)) {
8653                 printf("cli_get_ea_list_path failed (%s)\n",
8654                         nt_errstr(status));
8655                 goto out;
8656         }
8657
8658         /* Ensure the EA we set is there. */
8659         for (i=0; i<num_eas; i++) {
8660                 if (strcmp(eas[i].name, ea_name) == 0 &&
8661                                 eas[i].value.length == strlen(ea_value)+1 &&
8662                                 memcmp(eas[i].value.data,
8663                                         ea_value,
8664                                         eas[i].value.length) == 0) {
8665                         break;
8666                 }
8667         }
8668
8669         if (i == num_eas) {
8670                 printf("Didn't find EA on pathname %s\n",
8671                         fname);
8672                 goto out;
8673         }
8674
8675         num_eas = 0;
8676         TALLOC_FREE(eas);
8677
8678         /* Get the EA list on the symlink. Should return empty list. */
8679         status = cli_get_ea_list_path(cli,
8680                                 sname,
8681                                 frame,
8682                                 &num_eas,
8683                                 &eas);
8684
8685         if (!NT_STATUS_IS_OK(status)) {
8686                 printf("cli_get_ea_list_path failed (%s)\n",
8687                         nt_errstr(status));
8688                 goto out;
8689         }
8690
8691         if (num_eas != 0) {
8692                 printf("cli_get_ea_list_path failed (%s)\n",
8693                         nt_errstr(status));
8694                 goto out;
8695         }
8696
8697         /* Set an EA on the symlink. Should fail. */
8698         status = cli_set_ea_path(cli,
8699                                 sname,
8700                                 ea_name,
8701                                 ea_value,
8702                                 strlen(ea_value)+1);
8703
8704         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8705                 printf("cli_set_ea_path on a symlink gave %s. "
8706                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8707                         nt_errstr(status));
8708                 goto out;
8709         }
8710
8711         printf("EA symlink test passed\n");
8712         correct = true;
8713
8714   out:
8715
8716         if (fnum != (uint16_t)-1) {
8717                 cli_close(cli, fnum);
8718                 fnum = (uint16_t)-1;
8719         }
8720
8721         cli_setatr(cli, sname, 0, 0);
8722         cli_posix_unlink(cli, sname);
8723         cli_setatr(cli, fname, 0, 0);
8724         cli_posix_unlink(cli, fname);
8725
8726         if (!torture_close_connection(cli)) {
8727                 correct = false;
8728         }
8729
8730         TALLOC_FREE(frame);
8731         return correct;
8732 }
8733
8734 /*
8735   Test POSIX locks are OFD-locks.
8736  */
8737 static bool run_posix_ofd_lock_test(int dummy)
8738 {
8739         static struct cli_state *cli;
8740         const char *fname = "posix_file";
8741         uint16_t fnum1 = (uint16_t)-1;
8742         uint16_t fnum2 = (uint16_t)-1;
8743         bool correct = false;
8744         NTSTATUS status;
8745         TALLOC_CTX *frame = NULL;
8746
8747         frame = talloc_stackframe();
8748
8749         printf("Starting POSIX ofd-lock test\n");
8750
8751         if (!torture_open_connection(&cli, 0)) {
8752                 TALLOC_FREE(frame);
8753                 return false;
8754         }
8755
8756         smbXcli_conn_set_sockopt(cli->conn, sockops);
8757
8758         status = torture_setup_unix_extensions(cli);
8759         if (!NT_STATUS_IS_OK(status)) {
8760                 TALLOC_FREE(frame);
8761                 return false;
8762         }
8763
8764         cli_setatr(cli, fname, 0, 0);
8765         cli_posix_unlink(cli, fname);
8766
8767         /* Open the file twice. */
8768         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8769                                 0600, &fnum1);
8770         if (!NT_STATUS_IS_OK(status)) {
8771                 printf("First POSIX open of %s failed\n", fname);
8772                 goto out;
8773         }
8774
8775         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8776         if (!NT_STATUS_IS_OK(status)) {
8777                 printf("First POSIX open of %s failed\n", fname);
8778                 goto out;
8779         }
8780
8781         /* Set a 0-50 lock on fnum1. */
8782         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8783         if (!NT_STATUS_IS_OK(status)) {
8784                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8785                 goto out;
8786         }
8787
8788         /* Set a 60-100 lock on fnum2. */
8789         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8790         if (!NT_STATUS_IS_OK(status)) {
8791                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8792                 goto out;
8793         }
8794
8795         /* close fnum1 - 0-50 lock should go away. */
8796         status = cli_close(cli, fnum1);
8797         if (!NT_STATUS_IS_OK(status)) {
8798                 printf("close failed (%s)\n",
8799                         nt_errstr(status));
8800                 goto out;
8801         }
8802         fnum1 = (uint16_t)-1;
8803
8804         /* Change the lock context. */
8805         cli_setpid(cli, cli_getpid(cli) + 1);
8806
8807         /* Re-open fnum1. */
8808         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8809         if (!NT_STATUS_IS_OK(status)) {
8810                 printf("Third POSIX open of %s failed\n", fname);
8811                 goto out;
8812         }
8813
8814         /* 60-100 lock should still be there. */
8815         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8816         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8817                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8818                 goto out;
8819         }
8820
8821         /* 0-50 lock should be gone. */
8822         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8823         if (!NT_STATUS_IS_OK(status)) {
8824                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8825                 goto out;
8826         }
8827
8828         printf("POSIX OFD lock test passed\n");
8829         correct = true;
8830
8831   out:
8832
8833         if (fnum1 != (uint16_t)-1) {
8834                 cli_close(cli, fnum1);
8835                 fnum1 = (uint16_t)-1;
8836         }
8837         if (fnum2 != (uint16_t)-1) {
8838                 cli_close(cli, fnum2);
8839                 fnum2 = (uint16_t)-1;
8840         }
8841
8842         cli_setatr(cli, fname, 0, 0);
8843         cli_posix_unlink(cli, fname);
8844
8845         if (!torture_close_connection(cli)) {
8846                 correct = false;
8847         }
8848
8849         TALLOC_FREE(frame);
8850         return correct;
8851 }
8852
8853 struct posix_blocking_state {
8854         struct tevent_context *ev;
8855         struct cli_state *cli1;
8856         uint16_t fnum1;
8857         struct cli_state *cli2;
8858         uint16_t fnum2;
8859         bool gotblocked;
8860         bool gotecho;
8861 };
8862
8863 static void posix_blocking_locked(struct tevent_req *subreq);
8864 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8865 static void posix_blocking_gotecho(struct tevent_req *subreq);
8866 static void posix_blocking_unlocked(struct tevent_req *subreq);
8867
8868 static struct tevent_req *posix_blocking_send(
8869         TALLOC_CTX *mem_ctx,
8870         struct tevent_context *ev,
8871         struct cli_state *cli1,
8872         uint16_t fnum1,
8873         struct cli_state *cli2,
8874         uint16_t fnum2)
8875 {
8876         struct tevent_req *req = NULL, *subreq = NULL;
8877         struct posix_blocking_state *state = NULL;
8878
8879         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8880         if (req == NULL) {
8881                 return NULL;
8882         }
8883         state->ev = ev;
8884         state->cli1 = cli1;
8885         state->fnum1 = fnum1;
8886         state->cli2 = cli2;
8887         state->fnum2 = fnum2;
8888
8889         subreq = cli_posix_lock_send(
8890                 state,
8891                 state->ev,
8892                 state->cli1,
8893                 state->fnum1,
8894                 0,
8895                 1,
8896                 false,
8897                 WRITE_LOCK);
8898         if (tevent_req_nomem(subreq, req)) {
8899                 return tevent_req_post(req, ev);
8900         }
8901         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8902         return req;
8903 }
8904
8905 static void posix_blocking_locked(struct tevent_req *subreq)
8906 {
8907         struct tevent_req *req = tevent_req_callback_data(
8908                 subreq, struct tevent_req);
8909         struct posix_blocking_state *state = tevent_req_data(
8910                 req, struct posix_blocking_state);
8911         NTSTATUS status;
8912
8913         status = cli_posix_lock_recv(subreq);
8914         TALLOC_FREE(subreq);
8915         if (tevent_req_nterror(req, status)) {
8916                 return;
8917         }
8918
8919         subreq = cli_posix_lock_send(
8920                 state,
8921                 state->ev,
8922                 state->cli2,
8923                 state->fnum2,
8924                 0,
8925                 1,
8926                 true,
8927                 WRITE_LOCK);
8928         if (tevent_req_nomem(subreq, req)) {
8929                 return;
8930         }
8931         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8932
8933         /* Make sure the blocking request is delivered */
8934         subreq = cli_echo_send(
8935                 state,
8936                 state->ev,
8937                 state->cli2,
8938                 1,
8939                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8940         if (tevent_req_nomem(subreq, req)) {
8941                 return;
8942         }
8943         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8944 }
8945
8946 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8947 {
8948         struct tevent_req *req = tevent_req_callback_data(
8949                 subreq, struct tevent_req);
8950         struct posix_blocking_state *state = tevent_req_data(
8951                 req, struct posix_blocking_state);
8952         NTSTATUS status;
8953
8954         status = cli_posix_lock_recv(subreq);
8955         TALLOC_FREE(subreq);
8956         if (tevent_req_nterror(req, status)) {
8957                 return;
8958         }
8959         if (!state->gotecho) {
8960                 printf("blocked req got through before echo\n");
8961                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8962                 return;
8963         }
8964         tevent_req_done(req);
8965 }
8966
8967 static void posix_blocking_gotecho(struct tevent_req *subreq)
8968 {
8969         struct tevent_req *req = tevent_req_callback_data(
8970                 subreq, struct tevent_req);
8971         struct posix_blocking_state *state = tevent_req_data(
8972                 req, struct posix_blocking_state);
8973         NTSTATUS status;
8974
8975         status = cli_echo_recv(subreq);
8976         TALLOC_FREE(subreq);
8977         if (tevent_req_nterror(req, status)) {
8978                 return;
8979         }
8980         if (state->gotblocked) {
8981                 printf("blocked req got through before echo\n");
8982                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8983                 return;
8984         }
8985         state->gotecho = true;
8986
8987         subreq = cli_posix_lock_send(
8988                 state,
8989                 state->ev,
8990                 state->cli1,
8991                 state->fnum1,
8992                 0,
8993                 1,
8994                 false,
8995                 UNLOCK_LOCK);
8996         if (tevent_req_nomem(subreq, req)) {
8997                 return;
8998         }
8999         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9000 }
9001
9002 static void posix_blocking_unlocked(struct tevent_req *subreq)
9003 {
9004         struct tevent_req *req = tevent_req_callback_data(
9005                 subreq, struct tevent_req);
9006         NTSTATUS status;
9007
9008         status = cli_posix_lock_recv(subreq);
9009         TALLOC_FREE(subreq);
9010         if (tevent_req_nterror(req, status)) {
9011                 return;
9012         }
9013         /* tevent_req_done in posix_blocking_gotlocked */
9014 }
9015
9016 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9017 {
9018         return tevent_req_simple_recv_ntstatus(req);
9019 }
9020
9021 static bool run_posix_blocking_lock(int dummy)
9022 {
9023         struct tevent_context *ev = NULL;
9024         struct cli_state *cli1 = NULL, *cli2 = NULL;
9025         const char *fname = "posix_blocking";
9026         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9027         struct tevent_req *req = NULL;
9028         NTSTATUS status;
9029         bool ret = false;
9030         bool ok;
9031
9032         printf("Starting posix blocking lock test\n");
9033
9034         ev = samba_tevent_context_init(NULL);
9035         if (ev == NULL) {
9036                 return false;
9037         }
9038
9039         ok = torture_open_connection(&cli1, 0);
9040         if (!ok) {
9041                 goto fail;
9042         }
9043         ok = torture_open_connection(&cli2, 0);
9044         if (!ok) {
9045                 goto fail;
9046         }
9047
9048         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9049
9050         status = torture_setup_unix_extensions(cli1);
9051         if (!NT_STATUS_IS_OK(status)) {
9052                 return false;
9053         }
9054
9055         status = torture_setup_unix_extensions(cli2);
9056         if (!NT_STATUS_IS_OK(status)) {
9057                 return false;
9058         }
9059
9060         cli_setatr(cli1, fname, 0, 0);
9061         cli_posix_unlink(cli1, fname);
9062
9063         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9064                                 0600, &fnum1);
9065         if (!NT_STATUS_IS_OK(status)) {
9066                 printf("First POSIX open of %s failed: %s\n",
9067                        fname,
9068                        nt_errstr(status));
9069                 goto fail;
9070         }
9071
9072         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9073         if (!NT_STATUS_IS_OK(status)) {
9074                 printf("Second POSIX open of %s failed: %s\n",
9075                        fname,
9076                        nt_errstr(status));
9077                 goto fail;
9078         }
9079
9080         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9081         if (req == NULL) {
9082                 printf("cli_posix_blocking failed\n");
9083                 goto fail;
9084         }
9085
9086         ok = tevent_req_poll_ntstatus(req, ev, &status);
9087         if (!ok) {
9088                 printf("tevent_req_poll_ntstatus failed: %s\n",
9089                        nt_errstr(status));
9090                 goto fail;
9091         }
9092         status = posix_blocking_recv(req);
9093         TALLOC_FREE(req);
9094         if (!NT_STATUS_IS_OK(status)) {
9095                 printf("posix_blocking_recv returned %s\n",
9096                        nt_errstr(status));
9097                 goto fail;
9098         }
9099
9100         ret = true;
9101 fail:
9102
9103         if (fnum1 != UINT16_MAX) {
9104                 cli_close(cli1, fnum1);
9105                 fnum1 = UINT16_MAX;
9106         }
9107         if (fnum2 != UINT16_MAX) {
9108                 cli_close(cli2, fnum2);
9109                 fnum2 = UINT16_MAX;
9110         }
9111
9112         if (cli1 != NULL) {
9113                 cli_setatr(cli1, fname, 0, 0);
9114                 cli_posix_unlink(cli1, fname);
9115         }
9116
9117         ok = true;
9118
9119         if (cli1 != NULL) {
9120                 ok &= torture_close_connection(cli1);
9121                 cli1 = NULL;
9122         }
9123         if (cli2 != NULL) {
9124                 ok &= torture_close_connection(cli2);
9125                 cli2 = NULL;
9126         }
9127
9128         if (!ok) {
9129                 ret = false;
9130         }
9131         TALLOC_FREE(ev);
9132         return ret;
9133 }
9134
9135 /*
9136   Test POSIX mkdir is case-sensitive.
9137  */
9138 static bool run_posix_mkdir_test(int dummy)
9139 {
9140         static struct cli_state *cli;
9141         const char *fname_foo = "POSIX_foo";
9142         const char *fname_foo_Foo = "POSIX_foo/Foo";
9143         const char *fname_foo_foo = "POSIX_foo/foo";
9144         const char *fname_Foo = "POSIX_Foo";
9145         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9146         const char *fname_Foo_foo = "POSIX_Foo/foo";
9147         bool correct = false;
9148         NTSTATUS status;
9149         TALLOC_CTX *frame = NULL;
9150         uint16_t fnum = (uint16_t)-1;
9151
9152         frame = talloc_stackframe();
9153
9154         printf("Starting POSIX mkdir test\n");
9155
9156         if (!torture_open_connection(&cli, 0)) {
9157                 TALLOC_FREE(frame);
9158                 return false;
9159         }
9160
9161         smbXcli_conn_set_sockopt(cli->conn, sockops);
9162
9163         status = torture_setup_unix_extensions(cli);
9164         if (!NT_STATUS_IS_OK(status)) {
9165                 TALLOC_FREE(frame);
9166                 return false;
9167         }
9168
9169         cli_posix_rmdir(cli, fname_foo_foo);
9170         cli_posix_rmdir(cli, fname_foo_Foo);
9171         cli_posix_rmdir(cli, fname_foo);
9172
9173         cli_posix_rmdir(cli, fname_Foo_foo);
9174         cli_posix_rmdir(cli, fname_Foo_Foo);
9175         cli_posix_rmdir(cli, fname_Foo);
9176
9177         /*
9178          * Create a file POSIX_foo then try
9179          * and use it in a directory path by
9180          * doing mkdir POSIX_foo/bar.
9181          * The mkdir should fail with
9182          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9183          */
9184
9185         status = cli_posix_open(cli,
9186                         fname_foo,
9187                         O_RDWR|O_CREAT,
9188                         0666,
9189                         &fnum);
9190         if (!NT_STATUS_IS_OK(status)) {
9191                 printf("cli_posix_open of %s failed error %s\n",
9192                         fname_foo,
9193                         nt_errstr(status));
9194                 goto out;
9195         }
9196
9197         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9198         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9199                 printf("cli_posix_mkdir of %s should fail with "
9200                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9201                         "%s instead\n",
9202                         fname_foo_foo,
9203                         nt_errstr(status));
9204                 goto out;
9205         }
9206
9207         status = cli_close(cli, fnum);
9208         if (!NT_STATUS_IS_OK(status)) {
9209                 printf("cli_close failed %s\n", nt_errstr(status));
9210                 goto out;
9211         }
9212         fnum = (uint16_t)-1;
9213
9214         status = cli_posix_unlink(cli, fname_foo);
9215         if (!NT_STATUS_IS_OK(status)) {
9216                 printf("cli_posix_unlink of %s failed error %s\n",
9217                         fname_foo,
9218                         nt_errstr(status));
9219                 goto out;
9220         }
9221
9222         /*
9223          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9224          * posix_open, posix_unlink, on
9225          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9226          * not silently create POSIX_foo/foo.
9227          */
9228
9229         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9230         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9231                 printf("cli_posix_mkdir of %s should fail with "
9232                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9233                         "%s instead\n",
9234                         fname_foo_foo,
9235                         nt_errstr(status));
9236                 goto out;
9237         }
9238
9239         status = cli_posix_rmdir(cli, fname_foo_foo);
9240         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9241                 printf("cli_posix_rmdir of %s should fail with "
9242                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9243                         "%s instead\n",
9244                         fname_foo_foo,
9245                         nt_errstr(status));
9246                 goto out;
9247         }
9248
9249         status = cli_posix_open(cli,
9250                         fname_foo_foo,
9251                         O_RDWR|O_CREAT,
9252                         0666,
9253                         &fnum);
9254         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9255                 printf("cli_posix_open of %s should fail with "
9256                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9257                         "%s instead\n",
9258                         fname_foo_foo,
9259                         nt_errstr(status));
9260                 goto out;
9261         }
9262
9263         status = cli_posix_unlink(cli, fname_foo_foo);
9264         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9265                 printf("cli_posix_unlink of %s should fail with "
9266                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9267                         "%s instead\n",
9268                         fname_foo_foo,
9269                         nt_errstr(status));
9270                 goto out;
9271         }
9272
9273         status = cli_posix_mkdir(cli, fname_foo, 0777);
9274         if (!NT_STATUS_IS_OK(status)) {
9275                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9276                 goto out;
9277         }
9278
9279         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9280         if (!NT_STATUS_IS_OK(status)) {
9281                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9282                 goto out;
9283         }
9284
9285         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9286         if (!NT_STATUS_IS_OK(status)) {
9287                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9288                 goto out;
9289         }
9290
9291         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9292         if (!NT_STATUS_IS_OK(status)) {
9293                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9294                 goto out;
9295         }
9296
9297         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9298         if (!NT_STATUS_IS_OK(status)) {
9299                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9300                 goto out;
9301         }
9302
9303         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9304         if (!NT_STATUS_IS_OK(status)) {
9305                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9306                 goto out;
9307         }
9308
9309         printf("POSIX mkdir test passed\n");
9310         correct = true;
9311
9312   out:
9313
9314         if (fnum != (uint16_t)-1) {
9315                 cli_close(cli, fnum);
9316                 fnum = (uint16_t)-1;
9317         }
9318
9319         cli_posix_rmdir(cli, fname_foo_foo);
9320         cli_posix_rmdir(cli, fname_foo_Foo);
9321         cli_posix_rmdir(cli, fname_foo);
9322
9323         cli_posix_rmdir(cli, fname_Foo_foo);
9324         cli_posix_rmdir(cli, fname_Foo_Foo);
9325         cli_posix_rmdir(cli, fname_Foo);
9326
9327         if (!torture_close_connection(cli)) {
9328                 correct = false;
9329         }
9330
9331         TALLOC_FREE(frame);
9332         return correct;
9333 }
9334
9335 struct posix_acl_oplock_state {
9336         struct tevent_context *ev;
9337         struct cli_state *cli;
9338         bool *got_break;
9339         bool *acl_ret;
9340         NTSTATUS status;
9341 };
9342
9343 static void posix_acl_oplock_got_break(struct tevent_req *req)
9344 {
9345         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9346                 req, struct posix_acl_oplock_state);
9347         uint16_t fnum;
9348         uint8_t level;
9349         NTSTATUS status;
9350
9351         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9352         TALLOC_FREE(req);
9353         if (!NT_STATUS_IS_OK(status)) {
9354                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9355                        nt_errstr(status));
9356                 return;
9357         }
9358         *state->got_break = true;
9359
9360         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9361                                   NO_OPLOCK);
9362         if (req == NULL) {
9363                 printf("cli_oplock_ack_send failed\n");
9364                 return;
9365         }
9366 }
9367
9368 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9369 {
9370         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9371                 req, struct posix_acl_oplock_state);
9372         size_t ret_size = 0;
9373         char *ret_data = NULL;
9374
9375         state->status = cli_posix_getacl_recv(req,
9376                         state,
9377                         &ret_size,
9378                         &ret_data);
9379
9380         if (!NT_STATUS_IS_OK(state->status)) {
9381                 printf("cli_posix_getacl_recv returned %s\n",
9382                         nt_errstr(state->status));
9383         }
9384         *state->acl_ret = true;
9385 }
9386
9387 static bool run_posix_acl_oplock_test(int dummy)
9388 {
9389         struct tevent_context *ev;
9390         struct cli_state *cli1, *cli2;
9391         struct tevent_req *oplock_req, *getacl_req;
9392         const char *fname = "posix_acl_oplock";
9393         uint16_t fnum;
9394         int saved_use_oplocks = use_oplocks;
9395         NTSTATUS status;
9396         bool correct = true;
9397         bool got_break = false;
9398         bool acl_ret = false;
9399
9400         struct posix_acl_oplock_state *state;
9401
9402         printf("starting posix_acl_oplock test\n");
9403
9404         if (!torture_open_connection(&cli1, 0)) {
9405                 use_level_II_oplocks = false;
9406                 use_oplocks = saved_use_oplocks;
9407                 return false;
9408         }
9409
9410         if (!torture_open_connection(&cli2, 1)) {
9411                 use_level_II_oplocks = false;
9412                 use_oplocks = saved_use_oplocks;
9413                 return false;
9414         }
9415
9416         /* Setup posix on cli2 only. */
9417         status = torture_setup_unix_extensions(cli2);
9418         if (!NT_STATUS_IS_OK(status)) {
9419                 return false;
9420         }
9421
9422         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9423         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9424
9425         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9426
9427         /* Create the file on the Windows connection. */
9428         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9429                           &fnum);
9430         if (!NT_STATUS_IS_OK(status)) {
9431                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9432                 return false;
9433         }
9434
9435         status = cli_close(cli1, fnum);
9436         if (!NT_STATUS_IS_OK(status)) {
9437                 printf("close1 failed (%s)\n", nt_errstr(status));
9438                 return false;
9439         }
9440
9441         cli1->use_oplocks = true;
9442
9443         /* Open with oplock. */
9444         status = cli_ntcreate(cli1,
9445                         fname,
9446                         0,
9447                         FILE_READ_DATA,
9448                         FILE_ATTRIBUTE_NORMAL,
9449                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9450                         FILE_OPEN,
9451                         0,
9452                         0,
9453                         &fnum,
9454                         NULL);
9455
9456         if (!NT_STATUS_IS_OK(status)) {
9457                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9458                 return false;
9459         }
9460
9461         ev = samba_tevent_context_init(talloc_tos());
9462         if (ev == NULL) {
9463                 printf("tevent_context_init failed\n");
9464                 return false;
9465         }
9466
9467         state = talloc_zero(ev, struct posix_acl_oplock_state);
9468         if (state == NULL) {
9469                 printf("talloc failed\n");
9470                 return false;
9471         }
9472         state->ev = ev;
9473         state->cli = cli1;
9474         state->got_break = &got_break;
9475         state->acl_ret = &acl_ret;
9476
9477         oplock_req = cli_smb_oplock_break_waiter_send(
9478                 talloc_tos(), ev, cli1);
9479         if (oplock_req == NULL) {
9480                 printf("cli_smb_oplock_break_waiter_send failed\n");
9481                 return false;
9482         }
9483         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9484
9485         /* Get ACL on POSIX connection - should break oplock. */
9486         getacl_req = cli_posix_getacl_send(talloc_tos(),
9487                                 ev,
9488                                 cli2,
9489                                 fname);
9490         if (getacl_req == NULL) {
9491                 printf("cli_posix_getacl_send failed\n");
9492                 return false;
9493         }
9494         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9495
9496         while (!got_break || !acl_ret) {
9497                 int ret;
9498                 ret = tevent_loop_once(ev);
9499                 if (ret == -1) {
9500                         printf("tevent_loop_once failed: %s\n",
9501                                strerror(errno));
9502                         return false;
9503                 }
9504         }
9505
9506         if (!NT_STATUS_IS_OK(state->status)) {
9507                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9508                 correct = false;
9509         }
9510
9511         status = cli_close(cli1, fnum);
9512         if (!NT_STATUS_IS_OK(status)) {
9513                 printf("close2 failed (%s)\n", nt_errstr(status));
9514                 correct = false;
9515         }
9516
9517         status = cli_unlink(cli1,
9518                         fname,
9519                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9520         if (!NT_STATUS_IS_OK(status)) {
9521                 printf("unlink failed (%s)\n", nt_errstr(status));
9522                 correct = false;
9523         }
9524
9525         if (!torture_close_connection(cli1)) {
9526                 correct = false;
9527         }
9528         if (!torture_close_connection(cli2)) {
9529                 correct = false;
9530         }
9531
9532         if (!got_break) {
9533                 correct = false;
9534         }
9535
9536         printf("finished posix acl oplock test\n");
9537
9538         return correct;
9539 }
9540
9541 static bool run_posix_acl_shareroot_test(int dummy)
9542 {
9543         struct cli_state *cli;
9544         NTSTATUS status;
9545         bool correct = false;
9546         char *posix_acl = NULL;
9547         size_t posix_acl_len = 0;
9548         uint16_t num_file_acls = 0;
9549         uint16_t num_dir_acls = 0;
9550         uint16_t i;
9551         uint32_t expected_size = 0;
9552         bool got_user = false;
9553         bool got_group = false;
9554         bool got_other = false;
9555         TALLOC_CTX *frame = NULL;
9556
9557         frame = talloc_stackframe();
9558
9559         printf("starting posix_acl_shareroot test\n");
9560
9561         if (!torture_open_connection(&cli, 0)) {
9562                 TALLOC_FREE(frame);
9563                 return false;
9564         }
9565
9566         smbXcli_conn_set_sockopt(cli->conn, sockops);
9567
9568         status = torture_setup_unix_extensions(cli);
9569         if (!NT_STATUS_IS_OK(status)) {
9570                 printf("Failed to setup unix extensions\n");
9571                 goto out;
9572         }
9573
9574         /* Get the POSIX ACL on the root of the share. */
9575         status = cli_posix_getacl(cli,
9576                                 ".",
9577                                 frame,
9578                                 &posix_acl_len,
9579                                 &posix_acl);
9580
9581         if (!NT_STATUS_IS_OK(status)) {
9582                 printf("cli_posix_getacl of '.' failed (%s)\n",
9583                         nt_errstr(status));
9584                 goto out;
9585         }
9586
9587         if (posix_acl_len < 6 ||
9588                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9589                 printf("getfacl ., unknown POSIX acl version %u.\n",
9590                         (unsigned int)CVAL(posix_acl,0) );
9591                 goto out;
9592         }
9593
9594         num_file_acls = SVAL(posix_acl,2);
9595         num_dir_acls = SVAL(posix_acl,4);
9596         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9597                                 SMB_POSIX_ACL_ENTRY_SIZE*
9598                                 (num_file_acls+num_dir_acls);
9599
9600         if (posix_acl_len != expected_size) {
9601                 printf("incorrect POSIX acl buffer size "
9602                         "(should be %u, was %u).\n",
9603                         (unsigned int)expected_size,
9604                         (unsigned int)posix_acl_len);
9605                 goto out;
9606         }
9607
9608         /*
9609          * We don't need to know what the ACL's are
9610          * we just need to know we have at least 3
9611          * file entries (u,g,o).
9612          */
9613
9614         for (i = 0; i < num_file_acls; i++) {
9615                 unsigned char tagtype =
9616                         CVAL(posix_acl,
9617                                 SMB_POSIX_ACL_HEADER_SIZE+
9618                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9619
9620                 switch(tagtype) {
9621                         case SMB_POSIX_ACL_USER_OBJ:
9622                                 got_user = true;
9623                                 break;
9624                         case SMB_POSIX_ACL_GROUP_OBJ:
9625                                 got_group = true;
9626                                 break;
9627                         case SMB_POSIX_ACL_OTHER:
9628                                 got_other = true;
9629                                 break;
9630                         default:
9631                                 break;
9632                 }
9633         }
9634
9635         if (!got_user) {
9636                 printf("Missing user entry\n");
9637                 goto out;
9638         }
9639
9640         if (!got_group) {
9641                 printf("Missing group entry\n");
9642                 goto out;
9643         }
9644
9645         if (!got_other) {
9646                 printf("Missing other entry\n");
9647                 goto out;
9648         }
9649
9650         correct = true;
9651
9652   out:
9653
9654         if (!torture_close_connection(cli)) {
9655                 correct = false;
9656         }
9657
9658         printf("finished posix acl shareroot test\n");
9659         TALLOC_FREE(frame);
9660
9661         return correct;
9662 }
9663
9664 static uint32_t open_attrs_table[] = {
9665                 FILE_ATTRIBUTE_NORMAL,
9666                 FILE_ATTRIBUTE_ARCHIVE,
9667                 FILE_ATTRIBUTE_READONLY,
9668                 FILE_ATTRIBUTE_HIDDEN,
9669                 FILE_ATTRIBUTE_SYSTEM,
9670
9671                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9672                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9673                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9674                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9675                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9676                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9677
9678                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9679                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9680                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9681                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9682 };
9683
9684 struct trunc_open_results {
9685         unsigned int num;
9686         uint32_t init_attr;
9687         uint32_t trunc_attr;
9688         uint32_t result_attr;
9689 };
9690
9691 static struct trunc_open_results attr_results[] = {
9692         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9693         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9694         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9695         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9696         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9697         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9698         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9699         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9700         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9701         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9702         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9703         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9704         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9705         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9706         { 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 },
9707         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9708         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9709         { 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 },
9710         { 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 },
9711         { 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 },
9712         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9713         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9714         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9715         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9716         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9717         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9718 };
9719
9720 static bool run_openattrtest(int dummy)
9721 {
9722         static struct cli_state *cli1;
9723         const char *fname = "\\openattr.file";
9724         uint16_t fnum1;
9725         bool correct = True;
9726         uint32_t attr;
9727         unsigned int i, j, k, l;
9728         NTSTATUS status;
9729
9730         printf("starting open attr test\n");
9731
9732         if (!torture_open_connection(&cli1, 0)) {
9733                 return False;
9734         }
9735
9736         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9737
9738         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9739                 cli_setatr(cli1, fname, 0, 0);
9740                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9741
9742                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9743                                        open_attrs_table[i], FILE_SHARE_NONE,
9744                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9745                 if (!NT_STATUS_IS_OK(status)) {
9746                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9747                         return False;
9748                 }
9749
9750                 status = cli_close(cli1, fnum1);
9751                 if (!NT_STATUS_IS_OK(status)) {
9752                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9753                         return False;
9754                 }
9755
9756                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9757                         status = cli_ntcreate(cli1, fname, 0,
9758                                               FILE_READ_DATA|FILE_WRITE_DATA,
9759                                               open_attrs_table[j],
9760                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9761                                               0, 0, &fnum1, NULL);
9762                         if (!NT_STATUS_IS_OK(status)) {
9763                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9764                                         if (attr_results[l].num == k) {
9765                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9766                                                                 k, open_attrs_table[i],
9767                                                                 open_attrs_table[j],
9768                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9769                                                 correct = False;
9770                                         }
9771                                 }
9772
9773                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9774                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9775                                                         k, open_attrs_table[i], open_attrs_table[j],
9776                                                         nt_errstr(status));
9777                                         correct = False;
9778                                 }
9779 #if 0
9780                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9781 #endif
9782                                 k++;
9783                                 continue;
9784                         }
9785
9786                         status = cli_close(cli1, fnum1);
9787                         if (!NT_STATUS_IS_OK(status)) {
9788                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9789                                 return False;
9790                         }
9791
9792                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9793                         if (!NT_STATUS_IS_OK(status)) {
9794                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9795                                 return False;
9796                         }
9797
9798 #if 0
9799                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9800                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9801 #endif
9802
9803                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9804                                 if (attr_results[l].num == k) {
9805                                         if (attr != attr_results[l].result_attr ||
9806                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9807                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9808                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9809                                                 open_attrs_table[i],
9810                                                 open_attrs_table[j],
9811                                                 (unsigned int)attr,
9812                                                 attr_results[l].result_attr);
9813                                                 correct = False;
9814                                         }
9815                                         break;
9816                                 }
9817                         }
9818                         k++;
9819                 }
9820         }
9821
9822         cli_setatr(cli1, fname, 0, 0);
9823         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9824
9825         printf("open attr test %s.\n", correct ? "passed" : "failed");
9826
9827         if (!torture_close_connection(cli1)) {
9828                 correct = False;
9829         }
9830         return correct;
9831 }
9832
9833 static NTSTATUS list_fn(struct file_info *finfo,
9834                     const char *name, void *state)
9835 {
9836         int *matched = (int *)state;
9837         if (matched != NULL) {
9838                 *matched += 1;
9839         }
9840         return NT_STATUS_OK;
9841 }
9842
9843 /*
9844   test directory listing speed
9845  */
9846 static bool run_dirtest(int dummy)
9847 {
9848         int i;
9849         static struct cli_state *cli;
9850         uint16_t fnum;
9851         struct timeval core_start;
9852         bool correct = True;
9853         int matched;
9854
9855         printf("starting directory test\n");
9856
9857         if (!torture_open_connection(&cli, 0)) {
9858                 return False;
9859         }
9860
9861         smbXcli_conn_set_sockopt(cli->conn, sockops);
9862
9863         srandom(0);
9864         for (i=0;i<torture_numops;i++) {
9865                 fstring fname;
9866                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9867                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9868                         fprintf(stderr,"Failed to open %s\n", fname);
9869                         return False;
9870                 }
9871                 cli_close(cli, fnum);
9872         }
9873
9874         core_start = timeval_current();
9875
9876         matched = 0;
9877         cli_list(cli, "a*.*", 0, list_fn, &matched);
9878         printf("Matched %d\n", matched);
9879
9880         matched = 0;
9881         cli_list(cli, "b*.*", 0, list_fn, &matched);
9882         printf("Matched %d\n", matched);
9883
9884         matched = 0;
9885         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9886         printf("Matched %d\n", matched);
9887
9888         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9889
9890         srandom(0);
9891         for (i=0;i<torture_numops;i++) {
9892                 fstring fname;
9893                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9894                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9895         }
9896
9897         if (!torture_close_connection(cli)) {
9898                 correct = False;
9899         }
9900
9901         printf("finished dirtest\n");
9902
9903         return correct;
9904 }
9905
9906 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9907                    void *state)
9908 {
9909         struct cli_state *pcli = (struct cli_state *)state;
9910         fstring fname;
9911         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9912
9913         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9914                 return NT_STATUS_OK;
9915
9916         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9917                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9918                         printf("del_fn: failed to rmdir %s\n,", fname );
9919         } else {
9920                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9921                         printf("del_fn: failed to unlink %s\n,", fname );
9922         }
9923         return NT_STATUS_OK;
9924 }
9925
9926
9927 /*
9928    send a raw ioctl - used by the torture code
9929 */
9930 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9931                               uint16_t fnum,
9932                               uint32_t code,
9933                               DATA_BLOB *blob)
9934 {
9935         uint16_t vwv[3];
9936         NTSTATUS status;
9937
9938         PUSH_LE_U16(vwv + 0, 0, fnum);
9939         PUSH_LE_U16(vwv + 1, 0, code >> 16);
9940         PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9941
9942         status = cli_smb(talloc_tos(),
9943                          cli,
9944                          SMBioctl,
9945                          0,
9946                          3,
9947                          vwv,
9948                          0,
9949                          NULL,
9950                          NULL,
9951                          0,
9952                          NULL,
9953                          NULL,
9954                          NULL,
9955                          NULL);
9956         if (!NT_STATUS_IS_OK(status)) {
9957                 return status;
9958         }
9959         *blob = data_blob_null;
9960         return NT_STATUS_OK;
9961 }
9962
9963 /*
9964   sees what IOCTLs are supported
9965  */
9966 bool torture_ioctl_test(int dummy)
9967 {
9968         static struct cli_state *cli;
9969         uint16_t device, function;
9970         uint16_t fnum;
9971         const char *fname = "\\ioctl.dat";
9972         DATA_BLOB blob;
9973         NTSTATUS status;
9974
9975         if (!torture_open_connection(&cli, 0)) {
9976                 return False;
9977         }
9978
9979         printf("starting ioctl test\n");
9980
9981         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9982
9983         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9984         if (!NT_STATUS_IS_OK(status)) {
9985                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9986                 return False;
9987         }
9988
9989         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9990         printf("ioctl device info: %s\n", nt_errstr(status));
9991
9992         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9993         printf("ioctl job info: %s\n", nt_errstr(status));
9994
9995         for (device=0;device<0x100;device++) {
9996                 printf("ioctl test with device = 0x%x\n", device);
9997                 for (function=0;function<0x100;function++) {
9998                         uint32_t code = (device<<16) | function;
9999
10000                         status = cli_raw_ioctl(cli, fnum, code, &blob);
10001
10002                         if (NT_STATUS_IS_OK(status)) {
10003                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10004                                        (int)blob.length);
10005                                 data_blob_free(&blob);
10006                         }
10007                 }
10008         }
10009
10010         if (!torture_close_connection(cli)) {
10011                 return False;
10012         }
10013
10014         return True;
10015 }
10016
10017
10018 /*
10019   tries variants of chkpath
10020  */
10021 bool torture_chkpath_test(int dummy)
10022 {
10023         static struct cli_state *cli;
10024         uint16_t fnum;
10025         bool ret;
10026         NTSTATUS status;
10027
10028         if (!torture_open_connection(&cli, 0)) {
10029                 return False;
10030         }
10031
10032         printf("starting chkpath test\n");
10033
10034         /* cleanup from an old run */
10035         torture_deltree(cli, "\\chkpath.dir");
10036
10037         status = cli_mkdir(cli, "\\chkpath.dir");
10038         if (!NT_STATUS_IS_OK(status)) {
10039                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10040                 return False;
10041         }
10042
10043         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10044         if (!NT_STATUS_IS_OK(status)) {
10045                 printf("mkdir2 failed : %s\n", nt_errstr(status));
10046                 return False;
10047         }
10048
10049         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10050                           DENY_NONE, &fnum);
10051         if (!NT_STATUS_IS_OK(status)) {
10052                 printf("open1 failed (%s)\n", nt_errstr(status));
10053                 return False;
10054         }
10055         cli_close(cli, fnum);
10056
10057         status = cli_chkpath(cli, "\\chkpath.dir");
10058         if (!NT_STATUS_IS_OK(status)) {
10059                 printf("chkpath1 failed: %s\n", nt_errstr(status));
10060                 ret = False;
10061         }
10062
10063         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10064         if (!NT_STATUS_IS_OK(status)) {
10065                 printf("chkpath2 failed: %s\n", nt_errstr(status));
10066                 ret = False;
10067         }
10068
10069         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10070         if (!NT_STATUS_IS_OK(status)) {
10071                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10072                                   NT_STATUS_NOT_A_DIRECTORY);
10073         } else {
10074                 printf("* chkpath on a file should fail\n");
10075                 ret = False;
10076         }
10077
10078         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10079         if (!NT_STATUS_IS_OK(status)) {
10080                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10081                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
10082         } else {
10083                 printf("* chkpath on a non existent file should fail\n");
10084                 ret = False;
10085         }
10086
10087         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10088         if (!NT_STATUS_IS_OK(status)) {
10089                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10090                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
10091         } else {
10092                 printf("* chkpath on a non existent component should fail\n");
10093                 ret = False;
10094         }
10095
10096         torture_deltree(cli, "\\chkpath.dir");
10097
10098         if (!torture_close_connection(cli)) {
10099                 return False;
10100         }
10101
10102         return ret;
10103 }
10104
10105 static bool run_eatest(int dummy)
10106 {
10107         static struct cli_state *cli;
10108         const char *fname = "\\eatest.txt";
10109         bool correct = True;
10110         uint16_t fnum;
10111         size_t i, num_eas;
10112         struct ea_struct *ea_list = NULL;
10113         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10114         NTSTATUS status;
10115
10116         printf("starting eatest\n");
10117
10118         if (!torture_open_connection(&cli, 0)) {
10119                 talloc_destroy(mem_ctx);
10120                 return False;
10121         }
10122
10123         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10124
10125         status = cli_ntcreate(cli, fname, 0,
10126                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10127                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10128                               0x4044, 0, &fnum, NULL);
10129         if (!NT_STATUS_IS_OK(status)) {
10130                 printf("open failed - %s\n", nt_errstr(status));
10131                 talloc_destroy(mem_ctx);
10132                 return False;
10133         }
10134
10135         for (i = 0; i < 10; i++) {
10136                 fstring ea_name, ea_val;
10137
10138                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10139                 memset(ea_val, (char)i+1, i+1);
10140                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10141                 if (!NT_STATUS_IS_OK(status)) {
10142                         printf("ea_set of name %s failed - %s\n", ea_name,
10143                                nt_errstr(status));
10144                         talloc_destroy(mem_ctx);
10145                         return False;
10146                 }
10147         }
10148
10149         cli_close(cli, fnum);
10150         for (i = 0; i < 10; i++) {
10151                 fstring ea_name, ea_val;
10152
10153                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10154                 memset(ea_val, (char)i+1, i+1);
10155                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10156                 if (!NT_STATUS_IS_OK(status)) {
10157                         printf("ea_set of name %s failed - %s\n", ea_name,
10158                                nt_errstr(status));
10159                         talloc_destroy(mem_ctx);
10160                         return False;
10161                 }
10162         }
10163
10164         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10165         if (!NT_STATUS_IS_OK(status)) {
10166                 printf("ea_get list failed - %s\n", nt_errstr(status));
10167                 correct = False;
10168         }
10169
10170         printf("num_eas = %d\n", (int)num_eas);
10171
10172         if (num_eas != 20) {
10173                 printf("Should be 20 EA's stored... failing.\n");
10174                 correct = False;
10175         }
10176
10177         for (i = 0; i < num_eas; i++) {
10178                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10179                 dump_data(0, ea_list[i].value.data,
10180                           ea_list[i].value.length);
10181         }
10182
10183         /* Setting EA's to zero length deletes them. Test this */
10184         printf("Now deleting all EA's - case independent....\n");
10185
10186 #if 1
10187         cli_set_ea_path(cli, fname, "", "", 0);
10188 #else
10189         for (i = 0; i < 20; i++) {
10190                 fstring ea_name;
10191                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10192                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10193                 if (!NT_STATUS_IS_OK(status)) {
10194                         printf("ea_set of name %s failed - %s\n", ea_name,
10195                                nt_errstr(status));
10196                         talloc_destroy(mem_ctx);
10197                         return False;
10198                 }
10199         }
10200 #endif
10201
10202         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10203         if (!NT_STATUS_IS_OK(status)) {
10204                 printf("ea_get list failed - %s\n", nt_errstr(status));
10205                 correct = False;
10206         }
10207
10208         printf("num_eas = %d\n", (int)num_eas);
10209         for (i = 0; i < num_eas; i++) {
10210                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10211                 dump_data(0, ea_list[i].value.data,
10212                           ea_list[i].value.length);
10213         }
10214
10215         if (num_eas != 0) {
10216                 printf("deleting EA's failed.\n");
10217                 correct = False;
10218         }
10219
10220         /* Try and delete a non existent EA. */
10221         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10222         if (!NT_STATUS_IS_OK(status)) {
10223                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10224                        nt_errstr(status));
10225                 correct = False;
10226         }
10227
10228         talloc_destroy(mem_ctx);
10229         if (!torture_close_connection(cli)) {
10230                 correct = False;
10231         }
10232
10233         return correct;
10234 }
10235
10236 static bool run_dirtest1(int dummy)
10237 {
10238         int i;
10239         static struct cli_state *cli;
10240         uint16_t fnum;
10241         int num_seen;
10242         bool correct = True;
10243
10244         printf("starting directory test\n");
10245
10246         if (!torture_open_connection(&cli, 0)) {
10247                 return False;
10248         }
10249
10250         smbXcli_conn_set_sockopt(cli->conn, sockops);
10251
10252         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10253         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10254         cli_rmdir(cli, "\\LISTDIR");
10255         cli_mkdir(cli, "\\LISTDIR");
10256
10257         /* Create 1000 files and 1000 directories. */
10258         for (i=0;i<1000;i++) {
10259                 fstring fname;
10260                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10261                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10262                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10263                                    0, 0, &fnum, NULL))) {
10264                         fprintf(stderr,"Failed to open %s\n", fname);
10265                         return False;
10266                 }
10267                 cli_close(cli, fnum);
10268         }
10269         for (i=0;i<1000;i++) {
10270                 fstring fname;
10271                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10272                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10273                         fprintf(stderr,"Failed to open %s\n", fname);
10274                         return False;
10275                 }
10276         }
10277
10278         /* Now ensure that doing an old list sees both files and directories. */
10279         num_seen = 0;
10280         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10281         printf("num_seen = %d\n", num_seen );
10282         /* We should see 100 files + 1000 directories + . and .. */
10283         if (num_seen != 2002)
10284                 correct = False;
10285
10286         /* Ensure if we have the "must have" bits we only see the
10287          * relevant entries.
10288          */
10289         num_seen = 0;
10290         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10291         printf("num_seen = %d\n", num_seen );
10292         if (num_seen != 1002)
10293                 correct = False;
10294
10295         num_seen = 0;
10296         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10297         printf("num_seen = %d\n", num_seen );
10298         if (num_seen != 1000)
10299                 correct = False;
10300
10301         /* Delete everything. */
10302         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10303         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10304         cli_rmdir(cli, "\\LISTDIR");
10305
10306 #if 0
10307         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10308         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10309         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10310 #endif
10311
10312         if (!torture_close_connection(cli)) {
10313                 correct = False;
10314         }
10315
10316         printf("finished dirtest1\n");
10317
10318         return correct;
10319 }
10320
10321 static bool run_error_map_extract(int dummy) {
10322
10323         static struct cli_state *c_dos;
10324         static struct cli_state *c_nt;
10325         NTSTATUS status;
10326
10327         uint32_t error;
10328
10329         uint32_t errnum;
10330         uint8_t errclass;
10331
10332         NTSTATUS nt_status;
10333
10334         fstring user;
10335
10336         /* NT-Error connection */
10337
10338         disable_spnego = true;
10339         if (!(c_nt = open_nbt_connection())) {
10340                 disable_spnego = false;
10341                 return False;
10342         }
10343         disable_spnego = false;
10344
10345         status = smbXcli_negprot(c_nt->conn,
10346                                  c_nt->timeout,
10347                                  PROTOCOL_CORE,
10348                                  PROTOCOL_NT1,
10349                                  NULL,
10350                                  NULL,
10351                                  NULL);
10352
10353         if (!NT_STATUS_IS_OK(status)) {
10354                 printf("%s rejected the NT-error negprot (%s)\n", host,
10355                        nt_errstr(status));
10356                 cli_shutdown(c_nt);
10357                 return False;
10358         }
10359
10360         status = cli_session_setup_anon(c_nt);
10361         if (!NT_STATUS_IS_OK(status)) {
10362                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10363                 return False;
10364         }
10365
10366         /* DOS-Error connection */
10367
10368         disable_spnego = true;
10369         force_dos_errors = true;
10370         if (!(c_dos = open_nbt_connection())) {
10371                 disable_spnego = false;
10372                 force_dos_errors = false;
10373                 return False;
10374         }
10375         disable_spnego = false;
10376         force_dos_errors = false;
10377
10378         status = smbXcli_negprot(c_dos->conn,
10379                                  c_dos->timeout,
10380                                  PROTOCOL_CORE,
10381                                  PROTOCOL_NT1,
10382                                  NULL,
10383                                  NULL,
10384                                  NULL);
10385         if (!NT_STATUS_IS_OK(status)) {
10386                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10387                        nt_errstr(status));
10388                 cli_shutdown(c_dos);
10389                 return False;
10390         }
10391
10392         status = cli_session_setup_anon(c_dos);
10393         if (!NT_STATUS_IS_OK(status)) {
10394                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10395                         host, nt_errstr(status));
10396                 return False;
10397         }
10398
10399         c_nt->map_dos_errors = false;
10400         c_dos->map_dos_errors = false;
10401
10402         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10403                 struct cli_credentials *user_creds = NULL;
10404
10405                 fstr_sprintf(user, "%X", error);
10406
10407                 user_creds = cli_session_creds_init(talloc_tos(),
10408                                                     user,
10409                                                     workgroup,
10410                                                     NULL, /* realm */
10411                                                     password,
10412                                                     false, /* use_kerberos */
10413                                                     false, /* fallback_after_kerberos */
10414                                                     false, /* use_ccache */
10415                                                     false); /* password_is_nt_hash */
10416                 if (user_creds == NULL) {
10417                         printf("cli_session_creds_init(%s) failed\n", user);
10418                         return false;
10419                 }
10420
10421                 status = cli_session_setup_creds(c_nt, user_creds);
10422                 if (NT_STATUS_IS_OK(status)) {
10423                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10424                 }
10425
10426                 /* Case #1: 32-bit NT errors */
10427                 if (!NT_STATUS_IS_DOS(status)) {
10428                         nt_status = status;
10429                 } else {
10430                         printf("/** Dos error on NT connection! (%s) */\n", 
10431                                nt_errstr(status));
10432                         nt_status = NT_STATUS(0xc0000000);
10433                 }
10434
10435                 status = cli_session_setup_creds(c_dos, user_creds);
10436                 if (NT_STATUS_IS_OK(status)) {
10437                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10438                 }
10439
10440                 /* Case #1: 32-bit NT errors */
10441                 if (NT_STATUS_IS_DOS(status)) {
10442                         printf("/** NT error on DOS connection! (%s) */\n", 
10443                                nt_errstr(status));
10444                         errnum = errclass = 0;
10445                 } else {
10446                         errclass = NT_STATUS_DOS_CLASS(status);
10447                         errnum = NT_STATUS_DOS_CODE(status);
10448                 }
10449
10450                 if (NT_STATUS_V(nt_status) != error) { 
10451                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10452                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10453                                get_nt_error_c_code(talloc_tos(), nt_status));
10454                 }
10455
10456                 printf("\t{%s,\t%s,\t%s},\n", 
10457                        smb_dos_err_class(errclass), 
10458                        smb_dos_err_name(errclass, errnum), 
10459                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10460
10461                 TALLOC_FREE(user_creds);
10462         }
10463         return True;
10464 }
10465
10466 static bool run_sesssetup_bench(int dummy)
10467 {
10468         static struct cli_state *c;
10469         const char *fname = "\\file.dat";
10470         uint16_t fnum;
10471         NTSTATUS status;
10472         int i;
10473
10474         if (!torture_open_connection(&c, 0)) {
10475                 return false;
10476         }
10477
10478         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10479                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10480                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10481         if (!NT_STATUS_IS_OK(status)) {
10482                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10483                 return false;
10484         }
10485
10486         for (i=0; i<torture_numops; i++) {
10487                 status = cli_session_setup_creds(c, torture_creds);
10488                 if (!NT_STATUS_IS_OK(status)) {
10489                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10490                                  __location__, nt_errstr(status));
10491                         return false;
10492                 }
10493
10494                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10495
10496                 status = cli_ulogoff(c);
10497                 if (!NT_STATUS_IS_OK(status)) {
10498                         d_printf("(%s) cli_ulogoff failed: %s\n",
10499                                  __location__, nt_errstr(status));
10500                         return false;
10501                 }
10502         }
10503
10504         return true;
10505 }
10506
10507 static bool subst_test(const char *str, const char *user, const char *domain,
10508                        uid_t uid, gid_t gid, const char *expected)
10509 {
10510         char *subst;
10511         bool result = true;
10512
10513         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10514
10515         if (strcmp(subst, expected) != 0) {
10516                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10517                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10518                        expected);
10519                 result = false;
10520         }
10521
10522         TALLOC_FREE(subst);
10523         return result;
10524 }
10525
10526 static void chain1_open_completion(struct tevent_req *req)
10527 {
10528         uint16_t fnum;
10529         NTSTATUS status;
10530         status = cli_openx_recv(req, &fnum);
10531         TALLOC_FREE(req);
10532
10533         d_printf("cli_openx_recv returned %s: %d\n",
10534                  nt_errstr(status),
10535                  NT_STATUS_IS_OK(status) ? fnum : -1);
10536 }
10537
10538 static void chain1_write_completion(struct tevent_req *req)
10539 {
10540         size_t written;
10541         NTSTATUS status;
10542         status = cli_write_andx_recv(req, &written);
10543         TALLOC_FREE(req);
10544
10545         d_printf("cli_write_andx_recv returned %s: %d\n",
10546                  nt_errstr(status),
10547                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10548 }
10549
10550 static void chain1_close_completion(struct tevent_req *req)
10551 {
10552         NTSTATUS status;
10553         bool *done = (bool *)tevent_req_callback_data_void(req);
10554
10555         status = cli_close_recv(req);
10556         *done = true;
10557
10558         TALLOC_FREE(req);
10559
10560         d_printf("cli_close returned %s\n", nt_errstr(status));
10561 }
10562
10563 static bool run_chain1(int dummy)
10564 {
10565         struct cli_state *cli1;
10566         struct tevent_context *evt = samba_tevent_context_init(NULL);
10567         struct tevent_req *reqs[3], *smbreqs[3];
10568         bool done = false;
10569         const char *str = "foobar";
10570         const char *fname = "\\test_chain";
10571         NTSTATUS status;
10572
10573         printf("starting chain1 test\n");
10574         if (!torture_open_connection(&cli1, 0)) {
10575                 return False;
10576         }
10577
10578         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10579
10580         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10581
10582         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10583                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10584         if (reqs[0] == NULL) return false;
10585         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10586
10587
10588         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10589                                         (const uint8_t *)str, 0, strlen(str)+1,
10590                                         smbreqs, 1, &smbreqs[1]);
10591         if (reqs[1] == NULL) return false;
10592         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10593
10594         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10595         if (reqs[2] == NULL) return false;
10596         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10597
10598         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10599         if (!NT_STATUS_IS_OK(status)) {
10600                 return false;
10601         }
10602
10603         while (!done) {
10604                 tevent_loop_once(evt);
10605         }
10606
10607         torture_close_connection(cli1);
10608         return True;
10609 }
10610
10611 static void chain2_sesssetup_completion(struct tevent_req *req)
10612 {
10613         NTSTATUS status;
10614         status = cli_session_setup_guest_recv(req);
10615         d_printf("sesssetup returned %s\n", nt_errstr(status));
10616 }
10617
10618 static void chain2_tcon_completion(struct tevent_req *req)
10619 {
10620         bool *done = (bool *)tevent_req_callback_data_void(req);
10621         NTSTATUS status;
10622         status = cli_tcon_andx_recv(req);
10623         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10624         *done = true;
10625 }
10626
10627 static bool run_chain2(int dummy)
10628 {
10629         struct cli_state *cli1;
10630         struct tevent_context *evt = samba_tevent_context_init(NULL);
10631         struct tevent_req *reqs[2], *smbreqs[2];
10632         bool done = false;
10633         NTSTATUS status;
10634         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10635
10636         printf("starting chain2 test\n");
10637         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10638                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10639         if (!NT_STATUS_IS_OK(status)) {
10640                 return False;
10641         }
10642
10643         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10644
10645         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10646                                                  &smbreqs[0]);
10647         if (reqs[0] == NULL) return false;
10648         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10649
10650         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10651                                        "?????", NULL, 0, &smbreqs[1]);
10652         if (reqs[1] == NULL) return false;
10653         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10654
10655         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10656         if (!NT_STATUS_IS_OK(status)) {
10657                 return false;
10658         }
10659
10660         while (!done) {
10661                 tevent_loop_once(evt);
10662         }
10663
10664         torture_close_connection(cli1);
10665         return True;
10666 }
10667
10668
10669 struct torture_createdel_state {
10670         struct tevent_context *ev;
10671         struct cli_state *cli;
10672 };
10673
10674 static void torture_createdel_created(struct tevent_req *subreq);
10675 static void torture_createdel_closed(struct tevent_req *subreq);
10676
10677 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10678                                                  struct tevent_context *ev,
10679                                                  struct cli_state *cli,
10680                                                  const char *name)
10681 {
10682         struct tevent_req *req, *subreq;
10683         struct torture_createdel_state *state;
10684
10685         req = tevent_req_create(mem_ctx, &state,
10686                                 struct torture_createdel_state);
10687         if (req == NULL) {
10688                 return NULL;
10689         }
10690         state->ev = ev;
10691         state->cli = cli;
10692
10693         subreq = cli_ntcreate_send(
10694                 state, ev, cli, name, 0,
10695                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10696                 FILE_ATTRIBUTE_NORMAL,
10697                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10698                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10699                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10700
10701         if (tevent_req_nomem(subreq, req)) {
10702                 return tevent_req_post(req, ev);
10703         }
10704         tevent_req_set_callback(subreq, torture_createdel_created, req);
10705         return req;
10706 }
10707
10708 static void torture_createdel_created(struct tevent_req *subreq)
10709 {
10710         struct tevent_req *req = tevent_req_callback_data(
10711                 subreq, struct tevent_req);
10712         struct torture_createdel_state *state = tevent_req_data(
10713                 req, struct torture_createdel_state);
10714         NTSTATUS status;
10715         uint16_t fnum;
10716
10717         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10718         TALLOC_FREE(subreq);
10719         if (tevent_req_nterror(req, status)) {
10720                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10721                            nt_errstr(status)));
10722                 return;
10723         }
10724
10725         subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10726         if (tevent_req_nomem(subreq, req)) {
10727                 return;
10728         }
10729         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10730 }
10731
10732 static void torture_createdel_closed(struct tevent_req *subreq)
10733 {
10734         struct tevent_req *req = tevent_req_callback_data(
10735                 subreq, struct tevent_req);
10736         NTSTATUS status;
10737
10738         status = cli_close_recv(subreq);
10739         if (tevent_req_nterror(req, status)) {
10740                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10741                 return;
10742         }
10743         tevent_req_done(req);
10744 }
10745
10746 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10747 {
10748         return tevent_req_simple_recv_ntstatus(req);
10749 }
10750
10751 struct torture_createdels_state {
10752         struct tevent_context *ev;
10753         struct cli_state *cli;
10754         const char *base_name;
10755         int sent;
10756         int received;
10757         int num_files;
10758         struct tevent_req **reqs;
10759 };
10760
10761 static void torture_createdels_done(struct tevent_req *subreq);
10762
10763 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10764                                                   struct tevent_context *ev,
10765                                                   struct cli_state *cli,
10766                                                   const char *base_name,
10767                                                   int num_parallel,
10768                                                   int num_files)
10769 {
10770         struct tevent_req *req;
10771         struct torture_createdels_state *state;
10772         int i;
10773
10774         req = tevent_req_create(mem_ctx, &state,
10775                                 struct torture_createdels_state);
10776         if (req == NULL) {
10777                 return NULL;
10778         }
10779         state->ev = ev;
10780         state->cli = cli;
10781         state->base_name = talloc_strdup(state, base_name);
10782         if (tevent_req_nomem(state->base_name, req)) {
10783                 return tevent_req_post(req, ev);
10784         }
10785         state->num_files = MAX(num_parallel, num_files);
10786         state->sent = 0;
10787         state->received = 0;
10788
10789         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10790         if (tevent_req_nomem(state->reqs, req)) {
10791                 return tevent_req_post(req, ev);
10792         }
10793
10794         for (i=0; i<num_parallel; i++) {
10795                 char *name;
10796
10797                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10798                                        state->sent);
10799                 if (tevent_req_nomem(name, req)) {
10800                         return tevent_req_post(req, ev);
10801                 }
10802                 state->reqs[i] = torture_createdel_send(
10803                         state->reqs, state->ev, state->cli, name);
10804                 if (tevent_req_nomem(state->reqs[i], req)) {
10805                         return tevent_req_post(req, ev);
10806                 }
10807                 name = talloc_move(state->reqs[i], &name);
10808                 tevent_req_set_callback(state->reqs[i],
10809                                         torture_createdels_done, req);
10810                 state->sent += 1;
10811         }
10812         return req;
10813 }
10814
10815 static void torture_createdels_done(struct tevent_req *subreq)
10816 {
10817         struct tevent_req *req = tevent_req_callback_data(
10818                 subreq, struct tevent_req);
10819         struct torture_createdels_state *state = tevent_req_data(
10820                 req, struct torture_createdels_state);
10821         size_t i, num_parallel = talloc_array_length(state->reqs);
10822         NTSTATUS status;
10823         char *name;
10824
10825         status = torture_createdel_recv(subreq);
10826         if (!NT_STATUS_IS_OK(status)){
10827                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10828                            nt_errstr(status)));
10829                 TALLOC_FREE(subreq);
10830                 tevent_req_nterror(req, status);
10831                 return;
10832         }
10833
10834         for (i=0; i<num_parallel; i++) {
10835                 if (subreq == state->reqs[i]) {
10836                         break;
10837                 }
10838         }
10839         if (i == num_parallel) {
10840                 DEBUG(10, ("received something we did not send\n"));
10841                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10842                 return;
10843         }
10844         TALLOC_FREE(state->reqs[i]);
10845
10846         if (state->sent >= state->num_files) {
10847                 tevent_req_done(req);
10848                 return;
10849         }
10850
10851         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10852                                state->sent);
10853         if (tevent_req_nomem(name, req)) {
10854                 return;
10855         }
10856         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10857                                                 state->cli, name);
10858         if (tevent_req_nomem(state->reqs[i], req)) {
10859                 return;
10860         }
10861         name = talloc_move(state->reqs[i], &name);
10862         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10863         state->sent += 1;
10864 }
10865
10866 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10867 {
10868         return tevent_req_simple_recv_ntstatus(req);
10869 }
10870
10871 struct swallow_notify_state {
10872         struct tevent_context *ev;
10873         struct cli_state *cli;
10874         uint16_t fnum;
10875         uint32_t completion_filter;
10876         bool recursive;
10877         bool (*fn)(uint32_t action, const char *name, void *priv);
10878         void *priv;
10879 };
10880
10881 static void swallow_notify_done(struct tevent_req *subreq);
10882
10883 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10884                                               struct tevent_context *ev,
10885                                               struct cli_state *cli,
10886                                               uint16_t fnum,
10887                                               uint32_t completion_filter,
10888                                               bool recursive,
10889                                               bool (*fn)(uint32_t action,
10890                                                          const char *name,
10891                                                          void *priv),
10892                                               void *priv)
10893 {
10894         struct tevent_req *req, *subreq;
10895         struct swallow_notify_state *state;
10896
10897         req = tevent_req_create(mem_ctx, &state,
10898                                 struct swallow_notify_state);
10899         if (req == NULL) {
10900                 return NULL;
10901         }
10902         state->ev = ev;
10903         state->cli = cli;
10904         state->fnum = fnum;
10905         state->completion_filter = completion_filter;
10906         state->recursive = recursive;
10907         state->fn = fn;
10908         state->priv = priv;
10909
10910         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10911                                  0xffff, state->completion_filter,
10912                                  state->recursive);
10913         if (tevent_req_nomem(subreq, req)) {
10914                 return tevent_req_post(req, ev);
10915         }
10916         tevent_req_set_callback(subreq, swallow_notify_done, req);
10917         return req;
10918 }
10919
10920 static void swallow_notify_done(struct tevent_req *subreq)
10921 {
10922         struct tevent_req *req = tevent_req_callback_data(
10923                 subreq, struct tevent_req);
10924         struct swallow_notify_state *state = tevent_req_data(
10925                 req, struct swallow_notify_state);
10926         NTSTATUS status;
10927         uint32_t i, num_changes;
10928         struct notify_change *changes;
10929
10930         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10931         TALLOC_FREE(subreq);
10932         if (!NT_STATUS_IS_OK(status)) {
10933                 DEBUG(10, ("cli_notify_recv returned %s\n",
10934                            nt_errstr(status)));
10935                 tevent_req_nterror(req, status);
10936                 return;
10937         }
10938
10939         for (i=0; i<num_changes; i++) {
10940                 state->fn(changes[i].action, changes[i].name, state->priv);
10941         }
10942         TALLOC_FREE(changes);
10943
10944         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10945                                  0xffff, state->completion_filter,
10946                                  state->recursive);
10947         if (tevent_req_nomem(subreq, req)) {
10948                 return;
10949         }
10950         tevent_req_set_callback(subreq, swallow_notify_done, req);
10951 }
10952
10953 static bool print_notifies(uint32_t action, const char *name, void *priv)
10954 {
10955         if (DEBUGLEVEL > 5) {
10956                 d_printf("%d %s\n", (int)action, name);
10957         }
10958         return true;
10959 }
10960
10961 static void notify_bench_done(struct tevent_req *req)
10962 {
10963         int *num_finished = (int *)tevent_req_callback_data_void(req);
10964         *num_finished += 1;
10965 }
10966
10967 static bool run_notify_bench(int dummy)
10968 {
10969         const char *dname = "\\notify-bench";
10970         struct tevent_context *ev;
10971         NTSTATUS status;
10972         uint16_t dnum;
10973         struct tevent_req *req1;
10974         struct tevent_req *req2 = NULL;
10975         int i, num_unc_names;
10976         int num_finished = 0;
10977
10978         printf("starting notify-bench test\n");
10979
10980         if (use_multishare_conn) {
10981                 char **unc_list;
10982                 unc_list = file_lines_load(multishare_conn_fname,
10983                                            &num_unc_names, 0, NULL);
10984                 if (!unc_list || num_unc_names <= 0) {
10985                         d_printf("Failed to load unc names list from '%s'\n",
10986                                  multishare_conn_fname);
10987                         return false;
10988                 }
10989                 TALLOC_FREE(unc_list);
10990         } else {
10991                 num_unc_names = 1;
10992         }
10993
10994         ev = samba_tevent_context_init(talloc_tos());
10995         if (ev == NULL) {
10996                 d_printf("tevent_context_init failed\n");
10997                 return false;
10998         }
10999
11000         for (i=0; i<num_unc_names; i++) {
11001                 struct cli_state *cli;
11002                 char *base_fname;
11003
11004                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11005                                              dname, i);
11006                 if (base_fname == NULL) {
11007                         return false;
11008                 }
11009
11010                 if (!torture_open_connection(&cli, i)) {
11011                         return false;
11012                 }
11013
11014                 status = cli_ntcreate(cli, dname, 0,
11015                                       MAXIMUM_ALLOWED_ACCESS,
11016                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11017                                       FILE_SHARE_DELETE,
11018                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11019                                       &dnum, NULL);
11020
11021                 if (!NT_STATUS_IS_OK(status)) {
11022                         d_printf("Could not create %s: %s\n", dname,
11023                                  nt_errstr(status));
11024                         return false;
11025                 }
11026
11027                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11028                                            FILE_NOTIFY_CHANGE_FILE_NAME |
11029                                            FILE_NOTIFY_CHANGE_DIR_NAME |
11030                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
11031                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
11032                                            false, print_notifies, NULL);
11033                 if (req1 == NULL) {
11034                         d_printf("Could not create notify request\n");
11035                         return false;
11036                 }
11037
11038                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11039                                                base_fname, 10, torture_numops);
11040                 if (req2 == NULL) {
11041                         d_printf("Could not create createdels request\n");
11042                         return false;
11043                 }
11044                 TALLOC_FREE(base_fname);
11045
11046                 tevent_req_set_callback(req2, notify_bench_done,
11047                                         &num_finished);
11048         }
11049
11050         while (num_finished < num_unc_names) {
11051                 int ret;
11052                 ret = tevent_loop_once(ev);
11053                 if (ret != 0) {
11054                         d_printf("tevent_loop_once failed\n");
11055                         return false;
11056                 }
11057         }
11058
11059         if (!tevent_req_poll(req2, ev)) {
11060                 d_printf("tevent_req_poll failed\n");
11061         }
11062
11063         status = torture_createdels_recv(req2);
11064         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11065
11066         return true;
11067 }
11068
11069 static bool run_mangle1(int dummy)
11070 {
11071         struct cli_state *cli;
11072         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11073         uint16_t fnum;
11074         fstring alt_name;
11075         NTSTATUS status;
11076
11077         printf("starting mangle1 test\n");
11078         if (!torture_open_connection(&cli, 0)) {
11079                 return False;
11080         }
11081
11082         smbXcli_conn_set_sockopt(cli->conn, sockops);
11083
11084         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11085                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11086                               0, 0, &fnum, NULL);
11087         if (!NT_STATUS_IS_OK(status)) {
11088                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11089                 return false;
11090         }
11091         cli_close(cli, fnum);
11092
11093         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11094         if (!NT_STATUS_IS_OK(status)) {
11095                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11096                          nt_errstr(status));
11097                 return false;
11098         }
11099         d_printf("alt_name: %s\n", alt_name);
11100
11101         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11102         if (!NT_STATUS_IS_OK(status)) {
11103                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11104                          nt_errstr(status));
11105                 return false;
11106         }
11107         cli_close(cli, fnum);
11108
11109         status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11110         if (!NT_STATUS_IS_OK(status)) {
11111                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11112                          nt_errstr(status));
11113                 return false;
11114         }
11115
11116         return true;
11117 }
11118
11119 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11120                                                  const char *mask,
11121                                                  void *state)
11122 {
11123         if (f->short_name == NULL) {
11124                 return NT_STATUS_OK;
11125         }
11126
11127         if (strlen(f->short_name) == 0) {
11128                 return NT_STATUS_OK;
11129         }
11130
11131         printf("unexpected shortname: %s\n", f->short_name);
11132
11133         return NT_STATUS_OBJECT_NAME_INVALID;
11134 }
11135
11136 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11137                                             const char *mask,
11138                                             void *state)
11139 {
11140         char *name = state;
11141
11142         printf("name: %s\n", f->name);
11143         fstrcpy(name, f->name);
11144         return NT_STATUS_OK;
11145 }
11146
11147 static bool run_mangle_illegal(int dummy)
11148 {
11149         struct cli_state *cli = NULL;
11150         struct cli_state *cli_posix = NULL;
11151         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11152         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11153         char *mangled_path = NULL;
11154         uint16_t fnum;
11155         fstring name;
11156         fstring alt_name;
11157         NTSTATUS status;
11158
11159         printf("starting mangle-illegal test\n");
11160
11161         if (!torture_open_connection(&cli, 0)) {
11162                 return False;
11163         }
11164
11165         smbXcli_conn_set_sockopt(cli->conn, sockops);
11166
11167         if (!torture_open_connection(&cli_posix, 0)) {
11168                 return false;
11169         }
11170
11171         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11172
11173         status = torture_setup_unix_extensions(cli_posix);
11174         if (!NT_STATUS_IS_OK(status)) {
11175                 return false;
11176         }
11177
11178         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11179         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11180         if (!NT_STATUS_IS_OK(status)) {
11181                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11182                 return False;
11183         }
11184
11185         /*
11186          * Create a file with illegal NTFS characters and test that we
11187          * get a usable mangled name
11188          */
11189
11190         cli_setatr(cli_posix, illegal_fname, 0, 0);
11191         cli_posix_unlink(cli_posix, illegal_fname);
11192
11193         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11194                                 0600, &fnum);
11195         if (!NT_STATUS_IS_OK(status)) {
11196                 printf("POSIX create of %s failed (%s)\n",
11197                        illegal_fname, nt_errstr(status));
11198                 return false;
11199         }
11200
11201         status = cli_close(cli_posix, fnum);
11202         if (!NT_STATUS_IS_OK(status)) {
11203                 printf("close failed (%s)\n", nt_errstr(status));
11204                 return false;
11205         }
11206
11207         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11208         if (!NT_STATUS_IS_OK(status)) {
11209                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11210                 return false;
11211         }
11212
11213         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11214         if (mangled_path == NULL) {
11215                 return false;
11216         }
11217
11218         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11219         if (!NT_STATUS_IS_OK(status)) {
11220                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11221                 TALLOC_FREE(mangled_path);
11222                 return false;
11223         }
11224         TALLOC_FREE(mangled_path);
11225         cli_close(cli, fnum);
11226
11227         cli_setatr(cli_posix, illegal_fname, 0, 0);
11228         cli_posix_unlink(cli_posix, illegal_fname);
11229
11230         /*
11231          * Create a file with a long name and check that we got *no* short name.
11232          */
11233
11234         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11235                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11236                               0, 0, &fnum, NULL);
11237         if (!NT_STATUS_IS_OK(status)) {
11238                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11239                 return false;
11240         }
11241         cli_close(cli, fnum);
11242
11243         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11244         if (!NT_STATUS_IS_OK(status)) {
11245                 d_printf("cli_list failed\n");
11246                 return false;
11247         }
11248
11249         cli_unlink(cli, fname, 0);
11250         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11251
11252         if (!torture_close_connection(cli_posix)) {
11253                 return false;
11254         }
11255
11256         if (!torture_close_connection(cli)) {
11257                 return false;
11258         }
11259
11260         return true;
11261 }
11262
11263 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11264 {
11265         size_t *to_pull = (size_t *)priv;
11266         size_t thistime = *to_pull;
11267
11268         thistime = MIN(thistime, n);
11269         if (thistime == 0) {
11270                 return 0;
11271         }
11272
11273         memset(buf, 0, thistime);
11274         *to_pull -= thistime;
11275         return thistime;
11276 }
11277
11278 static bool run_windows_write(int dummy)
11279 {
11280         struct cli_state *cli1;
11281         uint16_t fnum;
11282         int i;
11283         bool ret = false;
11284         const char *fname = "\\writetest.txt";
11285         struct timeval start_time;
11286         double seconds;
11287         double kbytes;
11288         NTSTATUS status;
11289
11290         printf("starting windows_write test\n");
11291         if (!torture_open_connection(&cli1, 0)) {
11292                 return False;
11293         }
11294
11295         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11296         if (!NT_STATUS_IS_OK(status)) {
11297                 printf("open failed (%s)\n", nt_errstr(status));
11298                 return False;
11299         }
11300
11301         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11302
11303         start_time = timeval_current();
11304
11305         for (i=0; i<torture_numops; i++) {
11306                 uint8_t c = 0;
11307                 off_t start = i * torture_blocksize;
11308                 size_t to_pull = torture_blocksize - 1;
11309
11310                 status = cli_writeall(cli1, fnum, 0, &c,
11311                                       start + torture_blocksize - 1, 1, NULL);
11312                 if (!NT_STATUS_IS_OK(status)) {
11313                         printf("cli_write failed: %s\n", nt_errstr(status));
11314                         goto fail;
11315                 }
11316
11317                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11318                                   null_source, &to_pull);
11319                 if (!NT_STATUS_IS_OK(status)) {
11320                         printf("cli_push returned: %s\n", nt_errstr(status));
11321                         goto fail;
11322                 }
11323         }
11324
11325         seconds = timeval_elapsed(&start_time);
11326         kbytes = (double)torture_blocksize * torture_numops;
11327         kbytes /= 1024;
11328
11329         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11330                (double)seconds, (int)(kbytes/seconds));
11331
11332         ret = true;
11333  fail:
11334         cli_close(cli1, fnum);
11335         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11336         torture_close_connection(cli1);
11337         return ret;
11338 }
11339
11340 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11341 {
11342         size_t max_pdu = 0x1FFFF;
11343
11344         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11345                 max_pdu = 0xFFFFFF;
11346         }
11347
11348         if (smb1cli_conn_signing_is_active(cli->conn)) {
11349                 max_pdu = 0x1FFFF;
11350         }
11351
11352         if (smb1cli_conn_encryption_on(cli->conn)) {
11353                 max_pdu = CLI_BUFFER_SIZE;
11354         }
11355
11356         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11357                 len_requested &= 0xFFFF;
11358         }
11359
11360         return MIN(len_requested,
11361                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11362 }
11363
11364 static bool check_read_call(struct cli_state *cli,
11365                             uint16_t fnum,
11366                             uint8_t *buf,
11367                             size_t len_requested)
11368 {
11369         NTSTATUS status;
11370         struct tevent_req *subreq = NULL;
11371         ssize_t len_read = 0;
11372         size_t len_expected = 0;
11373         struct tevent_context *ev = NULL;
11374
11375         ev = samba_tevent_context_init(talloc_tos());
11376         if (ev == NULL) {
11377                 return false;
11378         }
11379
11380         subreq = cli_read_andx_send(talloc_tos(),
11381                                     ev,
11382                                     cli,
11383                                     fnum,
11384                                     0,
11385                                     len_requested);
11386
11387         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11388                 return false;
11389         }
11390
11391         status = cli_read_andx_recv(subreq, &len_read, &buf);
11392         if (!NT_STATUS_IS_OK(status)) {
11393                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11394                 return false;
11395         }
11396
11397         TALLOC_FREE(subreq);
11398         TALLOC_FREE(ev);
11399
11400         len_expected = calc_expected_return(cli, len_requested);
11401
11402         if (len_expected > 0x10000 && len_read == 0x10000) {
11403                 /* Windows servers only return a max of 0x10000,
11404                    doesn't matter if you set CAP_LARGE_READX in
11405                    the client sessionsetupX call or not. */
11406                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11407                         (unsigned int)len_requested);
11408         } else if (len_read != len_expected) {
11409                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11410                         (unsigned int)len_requested,
11411                         (unsigned int)len_read,
11412                         (unsigned int)len_expected);
11413                 return false;
11414         } else {
11415                 d_printf("Correct read reply.\n");
11416         }
11417
11418         return true;
11419 }
11420
11421 /* Test large readX variants. */
11422 static bool large_readx_tests(struct cli_state *cli,
11423                                 uint16_t fnum,
11424                                 uint8_t *buf)
11425 {
11426         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11427         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11428                 return false;
11429         }
11430         /* A read of 0x10000 should return 0x10000 bytes. */
11431         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11432                 return false;
11433         }
11434         /* A read of 0x10000 should return 0x10001 bytes. */
11435         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11436                 return false;
11437         }
11438         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11439            the requested number of bytes. */
11440         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11441                 return false;
11442         }
11443         /* A read of 1MB should return 1MB bytes (on Samba). */
11444         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11445                 return false;
11446         }
11447
11448         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11449                 return false;
11450         }
11451         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11452                 return false;
11453         }
11454         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11455                 return false;
11456         }
11457         return true;
11458 }
11459
11460 static bool run_large_readx(int dummy)
11461 {
11462         uint8_t *buf = NULL;
11463         struct cli_state *cli1 = NULL;
11464         struct cli_state *cli2 = NULL;
11465         bool correct = false;
11466         const char *fname = "\\large_readx.dat";
11467         NTSTATUS status;
11468         uint16_t fnum1 = UINT16_MAX;
11469         uint32_t normal_caps = 0;
11470         size_t file_size = 20*1024*1024;
11471         TALLOC_CTX *frame = talloc_stackframe();
11472         size_t i;
11473         struct {
11474                 const char *name;
11475                 enum smb_signing_setting signing_setting;
11476                 enum protocol_types protocol;
11477         } runs[] = {
11478                 {
11479                         .name = "NT1",
11480                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11481                         .protocol = PROTOCOL_NT1,
11482                 },{
11483                         .name = "NT1 - SIGNING_REQUIRED",
11484                         .signing_setting = SMB_SIGNING_REQUIRED,
11485                         .protocol = PROTOCOL_NT1,
11486                 },
11487         };
11488
11489         printf("starting large_readx test\n");
11490
11491         if (!torture_open_connection(&cli1, 0)) {
11492                 goto out;
11493         }
11494
11495         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11496
11497         if (!(normal_caps & CAP_LARGE_READX)) {
11498                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11499                         (unsigned int)normal_caps);
11500                 goto out;
11501         }
11502
11503         /* Create a file of size 4MB. */
11504         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11505                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11506                         0, 0, &fnum1, NULL);
11507
11508         if (!NT_STATUS_IS_OK(status)) {
11509                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11510                 goto out;
11511         }
11512
11513         /* Write file_size bytes. */
11514         buf = talloc_zero_array(frame, uint8_t, file_size);
11515         if (buf == NULL) {
11516                 goto out;
11517         }
11518
11519         status = cli_writeall(cli1,
11520                               fnum1,
11521                               0,
11522                               buf,
11523                               0,
11524                               file_size,
11525                               NULL);
11526         if (!NT_STATUS_IS_OK(status)) {
11527                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11528                 goto out;
11529         }
11530
11531         status = cli_close(cli1, fnum1);
11532         if (!NT_STATUS_IS_OK(status)) {
11533                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11534                 goto out;
11535         }
11536
11537         fnum1 = UINT16_MAX;
11538
11539         for (i=0; i < ARRAY_SIZE(runs); i++) {
11540                 enum smb_signing_setting saved_signing_setting = signing_state;
11541                 uint16_t fnum2 = -1;
11542
11543                 if (do_encrypt &&
11544                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11545                 {
11546                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11547                         continue;
11548                 }
11549
11550                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11551
11552                 signing_state = runs[i].signing_setting;
11553                 cli2 = open_nbt_connection();
11554                 signing_state = saved_signing_setting;
11555                 if (cli2 == NULL) {
11556                         goto out;
11557                 }
11558
11559                 status = smbXcli_negprot(cli2->conn,
11560                                          cli2->timeout,
11561                                          runs[i].protocol,
11562                                          runs[i].protocol,
11563                                          NULL,
11564                                          NULL,
11565                                          NULL);
11566                 if (!NT_STATUS_IS_OK(status)) {
11567                         goto out;
11568                 }
11569
11570                 status = cli_session_setup_creds(cli2, torture_creds);
11571                 if (!NT_STATUS_IS_OK(status)) {
11572                         goto out;
11573                 }
11574
11575                 status = cli_tree_connect(cli2,
11576                                         share,
11577                                         "?????",
11578                                         password);
11579                 if (!NT_STATUS_IS_OK(status)) {
11580                         goto out;
11581                 }
11582
11583                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11584
11585                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11586
11587                 if (!(normal_caps & CAP_LARGE_READX)) {
11588                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11589                                 (unsigned int)normal_caps);
11590                         goto out;
11591                 }
11592
11593                 if (do_encrypt) {
11594                         if (force_cli_encryption(cli2, share) == false) {
11595                                 goto out;
11596                         }
11597                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11598                         uint16_t major, minor;
11599                         uint32_t caplow, caphigh;
11600
11601                         status = cli_unix_extensions_version(cli2,
11602                                                              &major, &minor,
11603                                                              &caplow, &caphigh);
11604                         if (!NT_STATUS_IS_OK(status)) {
11605                                 goto out;
11606                         }
11607                 }
11608
11609                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11610                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11611                                 0, 0, &fnum2, NULL);
11612                 if (!NT_STATUS_IS_OK(status)) {
11613                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11614                         goto out;
11615                 }
11616
11617                 /* All reads must return less than file_size bytes. */
11618                 if (!large_readx_tests(cli2, fnum2, buf)) {
11619                         goto out;
11620                 }
11621
11622                 status = cli_close(cli2, fnum2);
11623                 if (!NT_STATUS_IS_OK(status)) {
11624                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11625                         goto out;
11626                 }
11627                 fnum2 = -1;
11628
11629                 if (!torture_close_connection(cli2)) {
11630                         goto out;
11631                 }
11632                 cli2 = NULL;
11633         }
11634
11635         correct = true;
11636         printf("Success on large_readx test\n");
11637
11638   out:
11639
11640         if (cli2) {
11641                 if (!torture_close_connection(cli2)) {
11642                         correct = false;
11643                 }
11644         }
11645
11646         if (cli1) {
11647                 if (fnum1 != UINT16_MAX) {
11648                         status = cli_close(cli1, fnum1);
11649                         if (!NT_STATUS_IS_OK(status)) {
11650                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11651                         }
11652                         fnum1 = UINT16_MAX;
11653                 }
11654
11655                 status = cli_unlink(cli1, fname,
11656                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11657                 if (!NT_STATUS_IS_OK(status)) {
11658                         printf("unlink failed (%s)\n", nt_errstr(status));
11659                 }
11660
11661                 if (!torture_close_connection(cli1)) {
11662                         correct = false;
11663                 }
11664         }
11665
11666         TALLOC_FREE(frame);
11667
11668         printf("finished large_readx test\n");
11669         return correct;
11670 }
11671
11672 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11673                                   const char *mask,
11674                                   void *private_data)
11675 {
11676         uint32_t *p_attr = (uint32_t *)private_data;
11677
11678         if (strequal(finfo->name, test_filename)) {
11679                 *p_attr = finfo->attr;
11680         }
11681
11682         return NT_STATUS_OK;
11683 }
11684
11685 static bool run_msdfs_attribute(int dummy)
11686 {
11687         static struct cli_state *cli;
11688         bool correct = false;
11689         uint32_t attr = 0;
11690         NTSTATUS status;
11691
11692         printf("Starting MSDFS-ATTRIBUTE test\n");
11693
11694         if (test_filename == NULL || test_filename[0] == '\0') {
11695                 printf("MSDFS-ATTRIBUTE test "
11696                         "needs -f filename-of-msdfs-link\n");
11697                 return false;
11698         }
11699
11700         /*
11701          * NB. We use torture_open_connection_flags() not
11702          * torture_open_connection() as the latter forces
11703          * SMB1.
11704          */
11705         if (!torture_open_connection_flags(&cli, 0, 0)) {
11706                 return false;
11707         }
11708
11709         smbXcli_conn_set_sockopt(cli->conn, sockops);
11710
11711         status = cli_list(cli,
11712                         "*",
11713                         FILE_ATTRIBUTE_DIRECTORY,
11714                         msdfs_attribute_list_fn,
11715                         &attr);
11716
11717         if (!NT_STATUS_IS_OK(status)) {
11718                 printf("cli_list failed with %s\n",
11719                         nt_errstr(status));
11720                 goto out;
11721         }
11722         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11723                 printf("file %s should have "
11724                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11725                         test_filename,
11726                         (unsigned int)attr);
11727                 goto out;
11728         }
11729
11730         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11731                 printf("file %s should have "
11732                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11733                         test_filename,
11734                         (unsigned int)attr);
11735                 goto out;
11736         }
11737
11738         correct = true;
11739
11740   out:
11741
11742         torture_close_connection(cli);
11743         return correct;
11744 }
11745
11746 static bool run_cli_echo(int dummy)
11747 {
11748         struct cli_state *cli;
11749         NTSTATUS status;
11750
11751         printf("starting cli_echo test\n");
11752         if (!torture_open_connection(&cli, 0)) {
11753                 return false;
11754         }
11755         smbXcli_conn_set_sockopt(cli->conn, sockops);
11756
11757         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11758
11759         d_printf("cli_echo returned %s\n", nt_errstr(status));
11760
11761         torture_close_connection(cli);
11762         return NT_STATUS_IS_OK(status);
11763 }
11764
11765 static int splice_status(off_t written, void *priv)
11766 {
11767         return true;
11768 }
11769
11770 static bool run_cli_splice(int dummy)
11771 {
11772         uint8_t *buf = NULL;
11773         struct cli_state *cli1 = NULL;
11774         bool correct = false;
11775         const char *fname_src = "\\splice_src.dat";
11776         const char *fname_dst = "\\splice_dst.dat";
11777         NTSTATUS status;
11778         uint16_t fnum1 = UINT16_MAX;
11779         uint16_t fnum2 = UINT16_MAX;
11780         size_t file_size = 2*1024*1024;
11781         size_t splice_size = 1*1024*1024 + 713;
11782         uint8_t digest1[16], digest2[16];
11783         off_t written = 0;
11784         size_t nread = 0;
11785         TALLOC_CTX *frame = talloc_stackframe();
11786
11787         printf("starting cli_splice test\n");
11788
11789         if (!torture_open_connection(&cli1, 0)) {
11790                 goto out;
11791         }
11792
11793         cli_unlink(cli1, fname_src,
11794                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11795         cli_unlink(cli1, fname_dst,
11796                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11797
11798         /* Create a file */
11799         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11800                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11801                         0, 0, &fnum1, NULL);
11802
11803         if (!NT_STATUS_IS_OK(status)) {
11804                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11805                 goto out;
11806         }
11807
11808         /* Write file_size bytes - must be bigger than splice_size. */
11809         buf = talloc_zero_array(frame, uint8_t, file_size);
11810         if (buf == NULL) {
11811                 d_printf("talloc_fail\n");
11812                 goto out;
11813         }
11814
11815         /* Fill it with random numbers. */
11816         generate_random_buffer(buf, file_size);
11817
11818         /* MD5 the first 1MB + 713 bytes. */
11819         gnutls_hash_fast(GNUTLS_DIG_MD5,
11820                          buf,
11821                          splice_size,
11822                          digest1);
11823
11824         status = cli_writeall(cli1,
11825                               fnum1,
11826                               0,
11827                               buf,
11828                               0,
11829                               file_size,
11830                               NULL);
11831         if (!NT_STATUS_IS_OK(status)) {
11832                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11833                 goto out;
11834         }
11835
11836         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11837                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11838                         0, 0, &fnum2, NULL);
11839
11840         if (!NT_STATUS_IS_OK(status)) {
11841                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11842                 goto out;
11843         }
11844
11845         /* Now splice 1MB + 713 bytes. */
11846         status = cli_splice(cli1,
11847                                 cli1,
11848                                 fnum1,
11849                                 fnum2,
11850                                 splice_size,
11851                                 0,
11852                                 0,
11853                                 &written,
11854                                 splice_status,
11855                                 NULL);
11856
11857         if (!NT_STATUS_IS_OK(status)) {
11858                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11859                 goto out;
11860         }
11861
11862         /* Clear the old buffer. */
11863         memset(buf, '\0', file_size);
11864
11865         /* Read the new file. */
11866         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11867         if (!NT_STATUS_IS_OK(status)) {
11868                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11869                 goto out;
11870         }
11871         if (nread != splice_size) {
11872                 d_printf("bad read of 0x%x, should be 0x%x\n",
11873                         (unsigned int)nread,
11874                         (unsigned int)splice_size);
11875                 goto out;
11876         }
11877
11878         /* MD5 the first 1MB + 713 bytes. */
11879         gnutls_hash_fast(GNUTLS_DIG_MD5,
11880                          buf,
11881                          splice_size,
11882                          digest2);
11883
11884         /* Must be the same. */
11885         if (memcmp(digest1, digest2, 16) != 0) {
11886                 d_printf("bad MD5 compare\n");
11887                 goto out;
11888         }
11889
11890         correct = true;
11891         printf("Success on cli_splice test\n");
11892
11893   out:
11894
11895         if (cli1) {
11896                 if (fnum1 != UINT16_MAX) {
11897                         cli_close(cli1, fnum1);
11898                 }
11899                 if (fnum2 != UINT16_MAX) {
11900                         cli_close(cli1, fnum2);
11901                 }
11902
11903                 cli_unlink(cli1, fname_src,
11904                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11905                 cli_unlink(cli1, fname_dst,
11906                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11907
11908                 if (!torture_close_connection(cli1)) {
11909                         correct = false;
11910                 }
11911         }
11912
11913         TALLOC_FREE(frame);
11914         return correct;
11915 }
11916
11917 static bool run_uid_regression_test(int dummy)
11918 {
11919         static struct cli_state *cli;
11920         int16_t old_vuid;
11921         int32_t old_cnum;
11922         bool correct = True;
11923         struct smbXcli_tcon *tcon_copy = NULL;
11924         NTSTATUS status;
11925
11926         printf("starting uid regression test\n");
11927
11928         if (!torture_open_connection(&cli, 0)) {
11929                 return False;
11930         }
11931
11932         smbXcli_conn_set_sockopt(cli->conn, sockops);
11933
11934         /* Ok - now save then logoff our current user. */
11935         old_vuid = cli_state_get_uid(cli);
11936
11937         status = cli_ulogoff(cli);
11938         if (!NT_STATUS_IS_OK(status)) {
11939                 d_printf("(%s) cli_ulogoff failed: %s\n",
11940                          __location__, nt_errstr(status));
11941                 correct = false;
11942                 goto out;
11943         }
11944
11945         cli_state_set_uid(cli, old_vuid);
11946
11947         /* Try an operation. */
11948         status = cli_mkdir(cli, "\\uid_reg_test");
11949         if (NT_STATUS_IS_OK(status)) {
11950                 d_printf("(%s) cli_mkdir succeeded\n",
11951                          __location__);
11952                 correct = false;
11953                 goto out;
11954         } else {
11955                 /* Should be bad uid. */
11956                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11957                                  NT_STATUS_USER_SESSION_DELETED)) {
11958                         correct = false;
11959                         goto out;
11960                 }
11961         }
11962
11963         old_cnum = cli_state_get_tid(cli);
11964         /*
11965          * This is an SMB1-only test.
11966          * Copy the tcon, not "save/restore".
11967          *
11968          * In SMB1 the cli_tdis() below frees
11969          * cli->smb1.tcon so we need a copy
11970          * of the struct to put back for the
11971          * second tdis call with invalid vuid.
11972          *
11973          * This is a test-only hack. Real client code
11974          * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11975          */
11976         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11977         if (tcon_copy == NULL) {
11978                 correct = false;
11979                 goto out;
11980         }
11981
11982         /* Now try a SMBtdis with the invalid vuid set to zero. */
11983         cli_state_set_uid(cli, 0);
11984
11985         /* This should succeed. */
11986         status = cli_tdis(cli);
11987
11988         if (NT_STATUS_IS_OK(status)) {
11989                 d_printf("First tdis with invalid vuid should succeed.\n");
11990         } else {
11991                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11992                 correct = false;
11993                 cli->smb1.tcon = tcon_copy;
11994                 goto out;
11995         }
11996
11997         cli->smb1.tcon = tcon_copy;
11998         cli_state_set_uid(cli, old_vuid);
11999         cli_state_set_tid(cli, old_cnum);
12000
12001         /* This should fail. */
12002         status = cli_tdis(cli);
12003         if (NT_STATUS_IS_OK(status)) {
12004                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12005                 correct = false;
12006                 goto out;
12007         } else {
12008                 /* Should be bad tid. */
12009                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12010                                 NT_STATUS_NETWORK_NAME_DELETED)) {
12011                         correct = false;
12012                         goto out;
12013                 }
12014         }
12015
12016         cli_rmdir(cli, "\\uid_reg_test");
12017
12018   out:
12019
12020         cli_shutdown(cli);
12021         return correct;
12022 }
12023
12024
12025 static const char *illegal_chars = "*\\/?<>|\":";
12026 static char force_shortname_chars[] = " +,.[];=\177";
12027
12028 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12029                              const char *mask, void *state)
12030 {
12031         struct cli_state *pcli = (struct cli_state *)state;
12032         fstring fname;
12033         NTSTATUS status = NT_STATUS_OK;
12034
12035         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12036
12037         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12038                 return NT_STATUS_OK;
12039
12040         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12041                 status = cli_rmdir(pcli, fname);
12042                 if (!NT_STATUS_IS_OK(status)) {
12043                         printf("del_fn: failed to rmdir %s\n,", fname );
12044                 }
12045         } else {
12046                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12047                 if (!NT_STATUS_IS_OK(status)) {
12048                         printf("del_fn: failed to unlink %s\n,", fname );
12049                 }
12050         }
12051         return status;
12052 }
12053
12054 struct sn_state {
12055         int matched;
12056         int i;
12057         bool val;
12058 };
12059
12060 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12061                               const char *name, void *state)
12062 {
12063         struct sn_state *s = (struct sn_state  *)state;
12064         int i = s->i;
12065
12066 #if 0
12067         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12068                 i, finfo->name, finfo->short_name);
12069 #endif
12070
12071         if (strchr(force_shortname_chars, i)) {
12072                 if (!finfo->short_name) {
12073                         /* Shortname not created when it should be. */
12074                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12075                                 __location__, finfo->name, i);
12076                         s->val = true;
12077                 }
12078         } else if (finfo->short_name){
12079                 /* Shortname created when it should not be. */
12080                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12081                         __location__, finfo->short_name, finfo->name);
12082                 s->val = true;
12083         }
12084         s->matched += 1;
12085         return NT_STATUS_OK;
12086 }
12087
12088 static bool run_shortname_test(int dummy)
12089 {
12090         static struct cli_state *cli;
12091         bool correct = True;
12092         int i;
12093         struct sn_state s;
12094         char fname[40];
12095         NTSTATUS status;
12096
12097         printf("starting shortname test\n");
12098
12099         if (!torture_open_connection(&cli, 0)) {
12100                 return False;
12101         }
12102
12103         smbXcli_conn_set_sockopt(cli->conn, sockops);
12104
12105         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12106         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12107         cli_rmdir(cli, "\\shortname");
12108
12109         status = cli_mkdir(cli, "\\shortname");
12110         if (!NT_STATUS_IS_OK(status)) {
12111                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12112                         __location__, nt_errstr(status));
12113                 correct = false;
12114                 goto out;
12115         }
12116
12117         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12118                 correct = false;
12119                 goto out;
12120         }
12121         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12122                 correct = false;
12123                 goto out;
12124         }
12125
12126         s.val = false;
12127
12128         for (i = 32; i < 128; i++) {
12129                 uint16_t fnum = (uint16_t)-1;
12130
12131                 s.i = i;
12132
12133                 if (strchr(illegal_chars, i)) {
12134                         continue;
12135                 }
12136                 fname[15] = i;
12137
12138                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12139                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12140                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12141                 if (!NT_STATUS_IS_OK(status)) {
12142                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12143                                 __location__, fname, nt_errstr(status));
12144                         correct = false;
12145                         goto out;
12146                 }
12147                 cli_close(cli, fnum);
12148
12149                 s.matched = 0;
12150                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12151                                   shortname_list_fn, &s);
12152                 if (s.matched != 1) {
12153                         d_printf("(%s) failed to list %s: %s\n",
12154                                 __location__, fname, nt_errstr(status));
12155                         correct = false;
12156                         goto out;
12157                 }
12158
12159                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12160                 if (!NT_STATUS_IS_OK(status)) {
12161                         d_printf("(%s) failed to delete %s: %s\n",
12162                                 __location__, fname, nt_errstr(status));
12163                         correct = false;
12164                         goto out;
12165                 }
12166
12167                 if (s.val) {
12168                         correct = false;
12169                         goto out;
12170                 }
12171         }
12172
12173   out:
12174
12175         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12176         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12177         cli_rmdir(cli, "\\shortname");
12178         torture_close_connection(cli);
12179         return correct;
12180 }
12181
12182 TLDAPRC callback_code;
12183
12184 static void pagedsearch_cb(struct tevent_req *req)
12185 {
12186         TLDAPRC rc;
12187         struct tldap_message *msg;
12188         char *dn;
12189
12190         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12191         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12192                 d_printf("tldap_search_paged_recv failed: %s\n",
12193                          tldap_rc2string(rc));
12194                 callback_code = rc;
12195                 return;
12196         }
12197         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12198                 TALLOC_FREE(msg);
12199                 return;
12200         }
12201         if (!tldap_entry_dn(msg, &dn)) {
12202                 d_printf("tldap_entry_dn failed\n");
12203                 return;
12204         }
12205         d_printf("%s\n", dn);
12206         TALLOC_FREE(msg);
12207 }
12208
12209 enum tldap_extended_val {
12210         EXTENDED_ZERO = 0,
12211         EXTENDED_ONE = 1,
12212         EXTENDED_NONE = 2,
12213 };
12214
12215 /*
12216  * Construct an extended dn control with either no value, 0 or 1
12217  *
12218  * No value and 0 are equivalent (non-hyphenated GUID)
12219  * 1 has the hyphenated GUID
12220  */
12221 static struct tldap_control *
12222 tldap_build_extended_control(enum tldap_extended_val val)
12223 {
12224         struct tldap_control empty_control;
12225         struct asn1_data *data;
12226
12227         ZERO_STRUCT(empty_control);
12228
12229         if (val != EXTENDED_NONE) {
12230                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12231
12232                 if (!data) {
12233                         return NULL;
12234                 }
12235
12236                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12237                         return NULL;
12238                 }
12239
12240                 if (!asn1_write_Integer(data, (int)val)) {
12241                         return NULL;
12242                 }
12243
12244                 if (!asn1_pop_tag(data)) {
12245                         return NULL;
12246                 }
12247
12248                 if (!asn1_blob(data, &empty_control.value)) {
12249                         return NULL;
12250                 }
12251         }
12252
12253         empty_control.oid = "1.2.840.113556.1.4.529";
12254         empty_control.critical = true;
12255
12256         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12257
12258 }
12259
12260 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12261                                       enum tldap_extended_val control_val)
12262 {
12263         struct tldap_control *control = tldap_build_extended_control(control_val);
12264         char *dn = NULL;
12265         struct tldap_message **msg;
12266         TLDAPRC rc;
12267
12268         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12269                           "(objectClass=*)", NULL, 0, 0,
12270                           control, 1, NULL,
12271                           0, 0, 0, 0, talloc_tos(), &msg);
12272         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12273                 d_printf("tldap_search for domain DN failed: %s\n",
12274                          tldap_errstr(talloc_tos(), ld, rc));
12275                 return false;
12276         }
12277
12278         if (!tldap_entry_dn(msg[0], &dn)) {
12279                 d_printf("tldap_search domain DN fetch failed: %s\n",
12280                          tldap_errstr(talloc_tos(), ld, rc));
12281                 return false;
12282         }
12283
12284         d_printf("%s\n", dn);
12285         {
12286                 uint32_t time_low;
12287                 uint32_t time_mid, time_hi_and_version;
12288                 uint32_t clock_seq[2];
12289                 uint32_t node[6];
12290                 char next;
12291
12292                 switch (control_val) {
12293                 case EXTENDED_NONE:
12294                 case EXTENDED_ZERO:
12295                         /*
12296                          * When reading GUIDs with hyphens, scanf will treat
12297                          * hyphen as a hex character (and counts as part of the
12298                          * width). This creates leftover GUID string which we
12299                          * check will for with 'next' and closing '>'.
12300                          */
12301                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12302                                          &time_low, &time_mid,
12303                                          &time_hi_and_version, &clock_seq[0],
12304                                          &clock_seq[1], &node[0], &node[1],
12305                                          &node[2], &node[3], &node[4],
12306                                          &node[5], &next)) {
12307                                 /* This GUID is good */
12308                         } else {
12309                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12310                                 return false;
12311                         }
12312
12313                         break;
12314                 case EXTENDED_ONE:
12315                         if (12 == sscanf(dn,
12316                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12317                                          &time_low, &time_mid,
12318                                          &time_hi_and_version, &clock_seq[0],
12319                                          &clock_seq[1], &node[0], &node[1],
12320                                          &node[2], &node[3], &node[4],
12321                                          &node[5], &next)) {
12322                                 /* This GUID is good */
12323                         } else {
12324                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12325                                 return false;
12326                         }
12327
12328                         break;
12329                 default:
12330                         return false;
12331                 }
12332         }
12333
12334         return true;
12335 }
12336
12337 static bool run_tldap(int dummy)
12338 {
12339         struct tldap_context *ld;
12340         int fd;
12341         TLDAPRC rc;
12342         NTSTATUS status;
12343         struct sockaddr_storage addr;
12344         struct tevent_context *ev;
12345         struct tevent_req *req;
12346         char *basedn;
12347         const char *filter;
12348
12349         if (!resolve_name(host, &addr, 0, false)) {
12350                 d_printf("could not find host %s\n", host);
12351                 return false;
12352         }
12353         status = open_socket_out(&addr, 389, 9999, &fd);
12354         if (!NT_STATUS_IS_OK(status)) {
12355                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12356                 return false;
12357         }
12358
12359         ld = tldap_context_create(talloc_tos(), fd);
12360         if (ld == NULL) {
12361                 close(fd);
12362                 d_printf("tldap_context_create failed\n");
12363                 return false;
12364         }
12365
12366         rc = tldap_fetch_rootdse(ld);
12367         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12368                 d_printf("tldap_fetch_rootdse failed: %s\n",
12369                          tldap_errstr(talloc_tos(), ld, rc));
12370                 return false;
12371         }
12372
12373         basedn = tldap_talloc_single_attribute(
12374                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12375         if (basedn == NULL) {
12376                 d_printf("no defaultNamingContext\n");
12377                 return false;
12378         }
12379         d_printf("defaultNamingContext: %s\n", basedn);
12380
12381         ev = samba_tevent_context_init(talloc_tos());
12382         if (ev == NULL) {
12383                 d_printf("tevent_context_init failed\n");
12384                 return false;
12385         }
12386
12387         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12388                                loadparm_init_s3(talloc_tos(),
12389                                                 loadparm_s3_helpers()),
12390                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12391
12392         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12393                 d_printf("tldap_gensec_bind failed\n");
12394                 return false;
12395         }
12396
12397         callback_code = TLDAP_SUCCESS;
12398
12399         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12400                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12401                                       NULL, 0, 0,
12402                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12403         if (req == NULL) {
12404                 d_printf("tldap_search_paged_send failed\n");
12405                 return false;
12406         }
12407         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12408
12409         tevent_req_poll(req, ev);
12410
12411         TALLOC_FREE(req);
12412
12413         rc = callback_code;
12414
12415         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12416                 d_printf("tldap_search with paging failed: %s\n",
12417                          tldap_errstr(talloc_tos(), ld, rc));
12418                 return false;
12419         }
12420
12421         /* test search filters against rootDSE */
12422         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12423                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12424
12425         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12426                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12427                           talloc_tos(), NULL);
12428         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12429                 d_printf("tldap_search with complex filter failed: %s\n",
12430                          tldap_errstr(talloc_tos(), ld, rc));
12431                 return false;
12432         }
12433
12434         /*
12435          * Tests to check for regression of:
12436          *
12437          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12438          *
12439          * TLDAP used here to pick apart the original string DN (with GUID)
12440          */
12441         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12442                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12443                          tldap_errstr(talloc_tos(), ld, rc));
12444                 return false;
12445         }
12446         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12447                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12448                          tldap_errstr(talloc_tos(), ld, rc));
12449                 return false;
12450         }
12451         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12452                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12453                          tldap_errstr(talloc_tos(), ld, rc));
12454                 return false;
12455         }
12456
12457         TALLOC_FREE(ld);
12458         return true;
12459 }
12460
12461 /* Torture test to ensure no regression of :
12462 https://bugzilla.samba.org/show_bug.cgi?id=7084
12463 */
12464
12465 static bool run_dir_createtime(int dummy)
12466 {
12467         struct cli_state *cli;
12468         const char *dname = "\\testdir_createtime";
12469         const char *fname = "\\testdir_createtime\\testfile";
12470         NTSTATUS status;
12471         struct timespec create_time;
12472         struct timespec create_time1;
12473         uint16_t fnum;
12474         bool ret = false;
12475         uint64_t ino;
12476
12477         if (!torture_open_connection(&cli, 0)) {
12478                 return false;
12479         }
12480
12481         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12482                 /* Ensure ino is zero, SMB2 gets a real one. */
12483                 ino = 0;
12484         } else {
12485                 /* Ensure ino is -1, SMB1 never gets a real one. */
12486                 ino = (uint64_t)-1;
12487         }
12488
12489         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12490         cli_rmdir(cli, dname);
12491
12492         status = cli_mkdir(cli, dname);
12493         if (!NT_STATUS_IS_OK(status)) {
12494                 printf("mkdir failed: %s\n", nt_errstr(status));
12495                 goto out;
12496         }
12497
12498         status = cli_qpathinfo2(cli,
12499                                 dname,
12500                                 &create_time,
12501                                 NULL,
12502                                 NULL,
12503                                 NULL,
12504                                 NULL,
12505                                 NULL,
12506                                 &ino,
12507                                 NULL);
12508         if (!NT_STATUS_IS_OK(status)) {
12509                 printf("cli_qpathinfo2 returned %s\n",
12510                        nt_errstr(status));
12511                 goto out;
12512         }
12513
12514         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12515                 /* SMB2 should always return an inode. */
12516                 if (ino == 0) {
12517                         printf("SMB2 bad inode (0)\n");
12518                         goto out;
12519                 }
12520         } else {
12521                 /* SMB1 must always return zero here. */
12522                 if (ino != 0) {
12523                         printf("SMB1 bad inode (!0)\n");
12524                         goto out;
12525                 }
12526         }
12527
12528         /* Sleep 3 seconds, then create a file. */
12529         sleep(3);
12530
12531         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12532                          DENY_NONE, &fnum);
12533         if (!NT_STATUS_IS_OK(status)) {
12534                 printf("cli_openx failed: %s\n", nt_errstr(status));
12535                 goto out;
12536         }
12537
12538         status = cli_qpathinfo2(cli,
12539                                 dname,
12540                                 &create_time1,
12541                                 NULL,
12542                                 NULL,
12543                                 NULL,
12544                                 NULL,
12545                                 NULL,
12546                                 NULL,
12547                                 NULL);
12548         if (!NT_STATUS_IS_OK(status)) {
12549                 printf("cli_qpathinfo2 (2) returned %s\n",
12550                        nt_errstr(status));
12551                 goto out;
12552         }
12553
12554         if (timespec_compare(&create_time1, &create_time)) {
12555                 printf("run_dir_createtime: create time was updated (error)\n");
12556         } else {
12557                 printf("run_dir_createtime: create time was not updated (correct)\n");
12558                 ret = true;
12559         }
12560
12561   out:
12562
12563         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12564         cli_rmdir(cli, dname);
12565         if (!torture_close_connection(cli)) {
12566                 ret = false;
12567         }
12568         return ret;
12569 }
12570
12571
12572 static bool run_streamerror(int dummy)
12573 {
12574         struct cli_state *cli;
12575         const char *dname = "\\testdir_streamerror";
12576         const char *streamname =
12577                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12578         NTSTATUS status;
12579         time_t change_time, access_time, write_time;
12580         off_t size;
12581         uint16_t fnum;
12582         uint32_t attr;
12583         bool ret = true;
12584
12585         if (!torture_open_connection(&cli, 0)) {
12586                 return false;
12587         }
12588
12589         torture_deltree(cli, dname);
12590
12591         status = cli_mkdir(cli, dname);
12592         if (!NT_STATUS_IS_OK(status)) {
12593                 printf("mkdir failed: %s\n", nt_errstr(status));
12594                 return false;
12595         }
12596
12597         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12598                                 &write_time, &size, &attr);
12599         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12600                 printf("pathinfo returned %s, expected "
12601                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12602                        nt_errstr(status));
12603                 ret = false;
12604         }
12605
12606         status = cli_ntcreate(cli, streamname, 0x16,
12607                               FILE_READ_DATA|FILE_READ_EA|
12608                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12609                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12610                               FILE_OPEN, 0, 0, &fnum, NULL);
12611
12612         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12613                 printf("ntcreate returned %s, expected "
12614                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12615                        nt_errstr(status));
12616                 ret = false;
12617         }
12618
12619
12620         cli_rmdir(cli, dname);
12621         return ret;
12622 }
12623
12624 struct pidtest_state {
12625         bool success;
12626         uint16_t vwv[1];
12627         DATA_BLOB data;
12628 };
12629
12630 static void pid_echo_done(struct tevent_req *subreq);
12631
12632 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12633                         struct tevent_context *ev,
12634                         struct cli_state *cli)
12635 {
12636         struct tevent_req *req, *subreq;
12637         struct pidtest_state *state;
12638
12639         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12640         if (req == NULL) {
12641                 return NULL;
12642         }
12643
12644         SSVAL(state->vwv, 0, 1);
12645         state->data = data_blob_const("hello", 5);
12646
12647         subreq = smb1cli_req_send(state,
12648                                 ev,
12649                                 cli->conn,
12650                                 SMBecho,
12651                                 0, 0, /* *_flags */
12652                                 0, 0, /* *_flags2 */
12653                                 cli->timeout,
12654                                 0xDEADBEEF, /* pid */
12655                                 NULL, /* tcon */
12656                                 NULL, /* session */
12657                                 ARRAY_SIZE(state->vwv), state->vwv,
12658                                 state->data.length, state->data.data);
12659
12660         if (tevent_req_nomem(subreq, req)) {
12661                 return tevent_req_post(req, ev);
12662         }
12663         tevent_req_set_callback(subreq, pid_echo_done, req);
12664         return req;
12665 }
12666
12667 static void pid_echo_done(struct tevent_req *subreq)
12668 {
12669         struct tevent_req *req = tevent_req_callback_data(
12670                 subreq, struct tevent_req);
12671         struct pidtest_state *state = tevent_req_data(
12672                 req, struct pidtest_state);
12673         NTSTATUS status;
12674         uint32_t num_bytes;
12675         uint8_t *bytes = NULL;
12676         struct iovec *recv_iov = NULL;
12677         uint8_t *phdr = NULL;
12678         uint16_t pidlow = 0;
12679         uint16_t pidhigh = 0;
12680         struct smb1cli_req_expected_response expected[] = {
12681         {
12682                 .status = NT_STATUS_OK,
12683                 .wct    = 1,
12684         },
12685         };
12686
12687         status = smb1cli_req_recv(subreq, state,
12688                                 &recv_iov,
12689                                 &phdr,
12690                                 NULL, /* pwct */
12691                                 NULL, /* pvwv */
12692                                 NULL, /* pvwv_offset */
12693                                 &num_bytes,
12694                                 &bytes,
12695                                 NULL, /* pbytes_offset */
12696                                 NULL, /* pinbuf */
12697                                 expected, ARRAY_SIZE(expected));
12698
12699         TALLOC_FREE(subreq);
12700
12701         if (!NT_STATUS_IS_OK(status)) {
12702                 tevent_req_nterror(req, status);
12703                 return;
12704         }
12705
12706         if (num_bytes != state->data.length) {
12707                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12708                 return;
12709         }
12710
12711         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12712                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12713                 return;
12714         }
12715
12716         /* Check pid low/high == DEADBEEF */
12717         pidlow = SVAL(phdr, HDR_PID);
12718         if (pidlow != 0xBEEF){
12719                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12720                         (unsigned int)pidlow);
12721                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12722                 return;
12723         }
12724         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12725         if (pidhigh != 0xDEAD){
12726                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12727                         (unsigned int)pidhigh);
12728                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12729                 return;
12730         }
12731
12732         tevent_req_done(req);
12733 }
12734
12735 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12736 {
12737         return tevent_req_simple_recv_ntstatus(req);
12738 }
12739
12740 static bool run_pidhigh(int dummy)
12741 {
12742         bool success = false;
12743         struct cli_state *cli = NULL;
12744         NTSTATUS status;
12745         struct tevent_context *ev = NULL;
12746         struct tevent_req *req = NULL;
12747         TALLOC_CTX *frame = talloc_stackframe();
12748
12749         printf("starting pid high test\n");
12750         if (!torture_open_connection(&cli, 0)) {
12751                 return false;
12752         }
12753         smbXcli_conn_set_sockopt(cli->conn, sockops);
12754
12755         ev = samba_tevent_context_init(frame);
12756         if (ev == NULL) {
12757                 goto fail;
12758         }
12759
12760         req = pid_echo_send(frame, ev, cli);
12761         if (req == NULL) {
12762                 goto fail;
12763         }
12764
12765         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12766                 goto fail;
12767         }
12768
12769         status = pid_echo_recv(req);
12770         if (NT_STATUS_IS_OK(status)) {
12771                 printf("pid high test ok\n");
12772                 success = true;
12773         }
12774
12775  fail:
12776
12777         TALLOC_FREE(frame);
12778         torture_close_connection(cli);
12779         return success;
12780 }
12781
12782 /*
12783   Test Windows open on a bad POSIX symlink.
12784  */
12785 static bool run_symlink_open_test(int dummy)
12786 {
12787         static struct cli_state *cli;
12788         const char *fname = "non_existant_file";
12789         const char *sname = "dangling_symlink";
12790         uint16_t fnum = (uint16_t)-1;
12791         bool correct = false;
12792         NTSTATUS status;
12793         TALLOC_CTX *frame = NULL;
12794
12795         frame = talloc_stackframe();
12796
12797         printf("Starting Windows bad symlink open test\n");
12798
12799         if (!torture_open_connection(&cli, 0)) {
12800                 TALLOC_FREE(frame);
12801                 return false;
12802         }
12803
12804         smbXcli_conn_set_sockopt(cli->conn, sockops);
12805
12806         status = torture_setup_unix_extensions(cli);
12807         if (!NT_STATUS_IS_OK(status)) {
12808                 TALLOC_FREE(frame);
12809                 return false;
12810         }
12811
12812         /* Ensure nothing exists. */
12813         cli_setatr(cli, fname, 0, 0);
12814         cli_posix_unlink(cli, fname);
12815         cli_setatr(cli, sname, 0, 0);
12816         cli_posix_unlink(cli, sname);
12817
12818         /* Create a symlink pointing nowhere. */
12819         status = cli_posix_symlink(cli, fname, sname);
12820         if (!NT_STATUS_IS_OK(status)) {
12821                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12822                         sname,
12823                         fname,
12824                         nt_errstr(status));
12825                 goto out;
12826         }
12827
12828         /* Now ensure that a Windows open doesn't hang. */
12829         status = cli_ntcreate(cli,
12830                         sname,
12831                         0,
12832                         FILE_READ_DATA|FILE_WRITE_DATA,
12833                         0,
12834                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12835                         FILE_OPEN_IF,
12836                         0x0,
12837                         0x0,
12838                         &fnum,
12839                         NULL);
12840
12841         /*
12842          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12843          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12844          * we use O_NOFOLLOW on the server or not.
12845          */
12846         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12847             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12848         {
12849                 correct = true;
12850         } else {
12851                 printf("cli_ntcreate of %s returned %s - should return"
12852                                 " either (%s) or (%s)\n",
12853                         sname,
12854                         nt_errstr(status),
12855                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12856                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12857                 goto out;
12858         }
12859
12860         correct = true;
12861
12862   out:
12863
12864         if (fnum != (uint16_t)-1) {
12865                 cli_close(cli, fnum);
12866                 fnum = (uint16_t)-1;
12867         }
12868
12869         cli_setatr(cli, sname, 0, 0);
12870         cli_posix_unlink(cli, sname);
12871         cli_setatr(cli, fname, 0, 0);
12872         cli_posix_unlink(cli, fname);
12873
12874         if (!torture_close_connection(cli)) {
12875                 correct = false;
12876         }
12877
12878         TALLOC_FREE(frame);
12879         return correct;
12880 }
12881
12882 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12883                                         const char *name,
12884                                         void *state)
12885 {
12886         char **mangled_name_return = (char **)state;
12887         bool is_mangled = strchr(finfo->name, '~');
12888
12889         if (is_mangled) {
12890                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12891                 if (*mangled_name_return == NULL) {
12892                         return NT_STATUS_NO_MEMORY;
12893                 }
12894         }
12895         return NT_STATUS_OK;
12896 }
12897
12898 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12899 {
12900         static struct cli_state *cli_posix = NULL;
12901         static struct cli_state *cli = NULL;
12902         uint16_t fnum = (uint16_t)-1;
12903         bool correct = false;
12904         const char *dname = "smb1_wild_mangle_unlink";
12905         const char *aname = "smb1_wild_mangle_unlink/a";
12906         const char *star_name = "smb1_wild_mangle_unlink/*";
12907         char *windows_unlink_name = NULL;
12908         char *mangled_name = NULL;
12909         NTSTATUS status;
12910
12911         printf("Starting SMB1 wild mangle unlink test\n");
12912
12913         /* Open a Windows connection. */
12914         if (!torture_open_connection(&cli, 0)) {
12915                 return false;
12916         }
12917
12918         smbXcli_conn_set_sockopt(cli->conn, sockops);
12919
12920         /* Open a POSIX connection. */
12921         if (!torture_open_connection(&cli_posix, 0)) {
12922                 goto out;
12923         }
12924
12925         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12926
12927         status = torture_setup_unix_extensions(cli_posix);
12928         if (!NT_STATUS_IS_OK(status)) {
12929                 printf("server doesn't support POSIX\n");
12930                 goto out;
12931         }
12932
12933         /* Start fresh. */
12934         torture_deltree(cli, dname);
12935
12936         /*
12937          * Create two files - 'a' and '*'.
12938          * We need POSIX extensions for this as '*'
12939          * is not a valid Windows name.
12940          */
12941
12942         status = cli_mkdir(cli, dname);
12943         if (!NT_STATUS_IS_OK(status)) {
12944                 printf("cli_mkdir of %s returned %s\n",
12945                         dname,
12946                         nt_errstr(status));
12947                 goto out;
12948         }
12949
12950         status = cli_posix_open(cli_posix,
12951                                 aname,
12952                                 O_RDWR|O_CREAT|O_EXCL,
12953                                 0660,
12954                                 &fnum);
12955         if (!NT_STATUS_IS_OK(status)) {
12956                 printf("cli_posix_open (create) of %s returned %s\n",
12957                         aname,
12958                         nt_errstr(status));
12959                 goto out;
12960         }
12961         status = cli_close(cli_posix, fnum);
12962         if (!NT_STATUS_IS_OK(status)) {
12963                 goto out;
12964         }
12965         status = cli_posix_open(cli_posix,
12966                                 star_name,
12967                                 O_RDWR|O_CREAT|O_EXCL,
12968                                 0660,
12969                                 &fnum);
12970         if (!NT_STATUS_IS_OK(status)) {
12971                 printf("cli_posix_open (create) of %s returned %s\n",
12972                         star_name,
12973                         nt_errstr(status));
12974                 goto out;
12975         }
12976         status = cli_close(cli_posix, fnum);
12977         if (!NT_STATUS_IS_OK(status)) {
12978                 goto out;
12979         }
12980
12981         status = cli_list(cli,
12982                         star_name,
12983                         0,
12984                         smb1_wild_mangle_list_fn,
12985                         &mangled_name);
12986         if (!NT_STATUS_IS_OK(status)) {
12987                 printf("cli_list of %s returned %s\n",
12988                         star_name,
12989                         nt_errstr(status));
12990                 goto out;
12991         }
12992
12993         if (mangled_name == NULL) {
12994                 goto out;
12995         }
12996
12997         printf("mangled_name = %s\n",
12998                 mangled_name);
12999
13000         /*
13001          * Try a Windows unlink with the mangled name.
13002          * This should *NOT* unlink the 'a' name.
13003          */
13004
13005         windows_unlink_name = talloc_asprintf(cli_posix,
13006                                         "%s\\%s",
13007                                         dname,
13008                                         mangled_name);
13009
13010         status = cli_unlink(cli, windows_unlink_name, 0);
13011         if (!NT_STATUS_IS_OK(status)) {
13012                 printf("cli_unlink of %s returned %s\n",
13013                         windows_unlink_name,
13014                         nt_errstr(status));
13015                 goto out;
13016         }
13017
13018         /* Does 'a' still exist ? */
13019         status = cli_posix_open(cli_posix,
13020                                 aname,
13021                                 O_RDONLY,
13022                                 0,
13023                                 &fnum);
13024         if (!NT_STATUS_IS_OK(status)) {
13025                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13026                         aname,
13027                         nt_errstr(status));
13028                 goto out;
13029         }
13030
13031         status = cli_close(cli_posix, fnum);
13032         if (!NT_STATUS_IS_OK(status)) {
13033                 goto out;
13034         }
13035
13036         correct = true;
13037
13038   out:
13039
13040         TALLOC_FREE(windows_unlink_name);
13041         TALLOC_FREE(mangled_name);
13042
13043         if (cli != NULL) {
13044                 torture_deltree(cli, dname);
13045                 torture_close_connection(cli);
13046         }
13047
13048         if (cli_posix != NULL) {
13049                 torture_close_connection(cli_posix);
13050         }
13051
13052         return correct;
13053 }
13054
13055 static bool run_smb1_wild_mangle_rename_test(int dummy)
13056 {
13057         static struct cli_state *cli_posix = NULL;
13058         static struct cli_state *cli = NULL;
13059         uint16_t fnum = (uint16_t)-1;
13060         bool correct = false;
13061         const char *dname = "smb1_wild_mangle_rename";
13062         const char *fooname = "smb1_wild_mangle_rename/foo";
13063         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13064         const char *wild_name = "smb1_wild_mangle_rename/*";
13065         char *windows_rename_src = NULL;
13066         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13067         char *mangled_name = NULL;
13068         NTSTATUS status;
13069
13070         printf("Starting SMB1 wild mangle rename test\n");
13071
13072         if (!torture_open_connection(&cli_posix, 0)) {
13073                 return false;
13074         }
13075
13076         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13077
13078         status = torture_setup_unix_extensions(cli_posix);
13079         if (!NT_STATUS_IS_OK(status)) {
13080                 printf("server doesn't support POSIX\n");
13081                 return false;
13082         }
13083
13084         /* Open a Windows connection. */
13085         if (!torture_open_connection(&cli, 0)) {
13086                 goto out;
13087         }
13088
13089         smbXcli_conn_set_sockopt(cli->conn, sockops);
13090
13091         /* Ensure we start from fresh. */
13092         torture_deltree(cli, dname);
13093
13094         /*
13095          * Create two files - 'foo' and 'fo*'.
13096          * We need POSIX extensions for this as 'fo*'
13097          * is not a valid Windows name.
13098          */
13099
13100         status = cli_posix_mkdir(cli_posix, dname, 0770);
13101         if (!NT_STATUS_IS_OK(status)) {
13102                 printf("cli_posix_mkdir of %s returned %s\n",
13103                         dname,
13104                         nt_errstr(status));
13105                 goto out;
13106         }
13107
13108         status = cli_posix_open(cli_posix,
13109                                 fooname,
13110                                 O_RDWR|O_CREAT|O_EXCL,
13111                                 0660,
13112                                 &fnum);
13113         if (!NT_STATUS_IS_OK(status)) {
13114                 printf("cli_posix_open (create) of %s returned %s\n",
13115                         fooname,
13116                         nt_errstr(status));
13117                 goto out;
13118         }
13119         status = cli_close(cli_posix, fnum);
13120         if (!NT_STATUS_IS_OK(status)) {
13121                 goto out;
13122         }
13123         status = cli_posix_open(cli_posix,
13124                                 foostar_name,
13125                                 O_RDWR|O_CREAT|O_EXCL,
13126                                 0660,
13127                                 &fnum);
13128         if (!NT_STATUS_IS_OK(status)) {
13129                 printf("cli_posix_open (create) of %s returned %s\n",
13130                         foostar_name,
13131                         nt_errstr(status));
13132                 goto out;
13133         }
13134         status = cli_close(cli_posix, fnum);
13135         if (!NT_STATUS_IS_OK(status)) {
13136                 goto out;
13137         }
13138
13139         /*
13140          * Get the mangled name. We can re-use the
13141          * previous smb1_wild_mangle_list_fn for this.
13142          */
13143
13144         status = cli_list(cli,
13145                         wild_name,
13146                         0,
13147                         smb1_wild_mangle_list_fn,
13148                         &mangled_name);
13149         if (!NT_STATUS_IS_OK(status)) {
13150                 printf("cli_list of %s returned %s\n",
13151                         wild_name,
13152                         nt_errstr(status));
13153                 goto out;
13154         }
13155
13156         if (mangled_name == NULL) {
13157                 goto out;
13158         }
13159
13160         printf("mangled_name = %s\n",
13161                 mangled_name);
13162
13163         /*
13164          * Try a Windows rename with the mangled name.
13165          * This should *NOT* rename the 'foo' name.
13166          */
13167
13168         windows_rename_src = talloc_asprintf(cli_posix,
13169                                         "%s\\%s",
13170                                         dname,
13171                                         mangled_name);
13172
13173         status = cli_rename(cli,
13174                         windows_rename_src,
13175                         windows_rename_dst,
13176                         false);
13177         if (!NT_STATUS_IS_OK(status)) {
13178                 printf("cli_rename of %s -> %s returned %s\n",
13179                         windows_rename_src,
13180                         windows_rename_dst,
13181                         nt_errstr(status));
13182                 goto out;
13183         }
13184
13185         /* Does 'foo' still exist ? */
13186         status = cli_posix_open(cli_posix,
13187                                 fooname,
13188                                 O_RDONLY,
13189                                 0,
13190                                 &fnum);
13191         if (!NT_STATUS_IS_OK(status)) {
13192                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13193                         fooname,
13194                         nt_errstr(status));
13195                 goto out;
13196         }
13197
13198         status = cli_close(cli_posix, fnum);
13199         if (!NT_STATUS_IS_OK(status)) {
13200                 goto out;
13201         }
13202
13203         correct = true;
13204
13205   out:
13206
13207         TALLOC_FREE(mangled_name);
13208         TALLOC_FREE(windows_rename_src);
13209
13210         if (cli != NULL) {
13211                 torture_deltree(cli, dname);
13212                 torture_close_connection(cli);
13213         }
13214
13215         torture_close_connection(cli_posix);
13216
13217         return correct;
13218 }
13219
13220 /*
13221  * Only testing minimal time strings, as the others
13222  * need (locale-dependent) guessing at what strftime does and
13223  * even may differ in builds.
13224  */
13225 static bool timesubst_test(void)
13226 {
13227         TALLOC_CTX *ctx = NULL;
13228         /* Sa 23. Dez 04:33:20 CET 2017 */
13229         const struct timeval tv = { 1514000000, 123 };
13230         const char* expect_minimal = "20171223_033320";
13231         const char* expect_minus   = "20171223_033320_000123";
13232         char *s;
13233         char *env_tz, *orig_tz = NULL;
13234         bool result = true;
13235
13236         ctx = talloc_new(NULL);
13237
13238         env_tz = getenv("TZ");
13239         if(env_tz) {
13240                 orig_tz = talloc_strdup(ctx, env_tz);
13241         }
13242         setenv("TZ", "UTC", 1);
13243
13244         s = minimal_timeval_string(ctx, &tv, false);
13245
13246         if(!s || strcmp(s, expect_minimal)) {
13247                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13248                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13249                 result = false;
13250         }
13251         TALLOC_FREE(s);
13252         s = minimal_timeval_string(ctx, &tv, true);
13253         if(!s || strcmp(s, expect_minus)) {
13254                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13255                        "[%s]\n", s ? s : "<nil>", expect_minus);
13256                 result = false;
13257         }
13258         TALLOC_FREE(s);
13259
13260         if(orig_tz) {
13261                 setenv("TZ", orig_tz, 1);
13262         }
13263
13264         TALLOC_FREE(ctx);
13265         return result;
13266 }
13267
13268 static bool run_local_substitute(int dummy)
13269 {
13270         bool ok = true;
13271
13272         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13273         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13274         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13275         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13276         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13277         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13278         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13279         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13280         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13281         /* Substitution depends on current time, so better test the underlying
13282            formatting function. At least covers %t. */
13283         ok &= timesubst_test();
13284
13285         /* Different captialization rules in sub_basic... */
13286
13287         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13288                        "blaDOM") == 0);
13289
13290         return ok;
13291 }
13292
13293 static bool run_local_base64(int dummy)
13294 {
13295         int i;
13296         bool ret = true;
13297
13298         for (i=1; i<2000; i++) {
13299                 DATA_BLOB blob1, blob2;
13300                 char *b64;
13301
13302                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13303                 blob1.length = i;
13304                 generate_random_buffer(blob1.data, blob1.length);
13305
13306                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13307                 if (b64 == NULL) {
13308                         d_fprintf(stderr, "base64_encode_data_blob failed "
13309                                   "for %d bytes\n", i);
13310                         ret = false;
13311                 }
13312                 blob2 = base64_decode_data_blob(b64);
13313                 TALLOC_FREE(b64);
13314
13315                 if (data_blob_cmp(&blob1, &blob2)) {
13316                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13317                                   "bytes\n", i);
13318                         ret = false;
13319                 }
13320                 TALLOC_FREE(blob1.data);
13321                 data_blob_free(&blob2);
13322         }
13323         return ret;
13324 }
13325
13326 static void parse_fn(const struct gencache_timeout *t,
13327                      DATA_BLOB blob,
13328                      void *private_data)
13329 {
13330         return;
13331 }
13332
13333 static bool run_local_gencache(int dummy)
13334 {
13335         char *val;
13336         time_t tm;
13337         DATA_BLOB blob;
13338         char v;
13339         struct memcache *mem;
13340         int i;
13341
13342         mem = memcache_init(NULL, 0);
13343         if (mem == NULL) {
13344                 d_printf("%s: memcache_init failed\n", __location__);
13345                 return false;
13346         }
13347         memcache_set_global(mem);
13348
13349         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13350                 d_printf("%s: gencache_set() failed\n", __location__);
13351                 return False;
13352         }
13353
13354         if (!gencache_get("foo", NULL, NULL, NULL)) {
13355                 d_printf("%s: gencache_get() failed\n", __location__);
13356                 return False;
13357         }
13358
13359         for (i=0; i<1000000; i++) {
13360                 gencache_parse("foo", parse_fn, NULL);
13361         }
13362
13363         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13364                 d_printf("%s: gencache_get() failed\n", __location__);
13365                 return False;
13366         }
13367         TALLOC_FREE(val);
13368
13369         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13370                 d_printf("%s: gencache_get() failed\n", __location__);
13371                 return False;
13372         }
13373
13374         if (strcmp(val, "bar") != 0) {
13375                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13376                          __location__, val, "bar");
13377                 TALLOC_FREE(val);
13378                 return False;
13379         }
13380
13381         TALLOC_FREE(val);
13382
13383         if (!gencache_del("foo")) {
13384                 d_printf("%s: gencache_del() failed\n", __location__);
13385                 return False;
13386         }
13387         if (gencache_del("foo")) {
13388                 d_printf("%s: second gencache_del() succeeded\n",
13389                          __location__);
13390                 return False;
13391         }
13392
13393         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13394                 d_printf("%s: gencache_get() on deleted entry "
13395                          "succeeded\n", __location__);
13396                 return False;
13397         }
13398
13399         blob = data_blob_string_const_null("bar");
13400         tm = time(NULL) + 60;
13401
13402         if (!gencache_set_data_blob("foo", blob, tm)) {
13403                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13404                 return False;
13405         }
13406
13407         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13408                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13409                 return False;
13410         }
13411
13412         if (strcmp((const char *)blob.data, "bar") != 0) {
13413                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13414                          __location__, (const char *)blob.data, "bar");
13415                 data_blob_free(&blob);
13416                 return False;
13417         }
13418
13419         data_blob_free(&blob);
13420
13421         if (!gencache_del("foo")) {
13422                 d_printf("%s: gencache_del() failed\n", __location__);
13423                 return False;
13424         }
13425         if (gencache_del("foo")) {
13426                 d_printf("%s: second gencache_del() succeeded\n",
13427                          __location__);
13428                 return False;
13429         }
13430
13431         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13432                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13433                          "succeeded\n", __location__);
13434                 return False;
13435         }
13436
13437         v = 1;
13438         blob.data = (uint8_t *)&v;
13439         blob.length = sizeof(v);
13440
13441         if (!gencache_set_data_blob("blob", blob, tm)) {
13442                 d_printf("%s: gencache_set_data_blob() failed\n",
13443                          __location__);
13444                 return false;
13445         }
13446         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13447                 d_printf("%s: gencache_get succeeded\n", __location__);
13448                 return false;
13449         }
13450
13451         return True;
13452 }
13453
13454 static bool rbt_testflags(struct db_context *db, const char *key,
13455                           const char *value)
13456 {
13457         bool ret = false;
13458         NTSTATUS status;
13459         struct db_record *rec;
13460
13461         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13462         if (rec == NULL) {
13463                 d_fprintf(stderr, "fetch_locked failed\n");
13464                 goto done;
13465         }
13466
13467         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13468         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13469                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13470                           nt_errstr(status));
13471                 goto done;
13472         }
13473
13474         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13475                                      TDB_INSERT);
13476         if (!NT_STATUS_IS_OK(status)) {
13477                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13478                           nt_errstr(status));
13479                 goto done;
13480         }
13481
13482         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13483         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13484                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13485                           nt_errstr(status));
13486                 goto done;
13487         }
13488
13489         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13490         if (!NT_STATUS_IS_OK(status)) {
13491                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13492                           nt_errstr(status));
13493                 goto done;
13494         }
13495
13496         ret = true;
13497 done:
13498         TALLOC_FREE(rec);
13499         return ret;
13500 }
13501
13502 static bool rbt_testval(struct db_context *db, const char *key,
13503                         const char *value)
13504 {
13505         struct db_record *rec;
13506         TDB_DATA data = string_tdb_data(value);
13507         bool ret = false;
13508         NTSTATUS status;
13509         TDB_DATA dbvalue;
13510
13511         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13512         if (rec == NULL) {
13513                 d_fprintf(stderr, "fetch_locked failed\n");
13514                 goto done;
13515         }
13516         status = dbwrap_record_store(rec, data, 0);
13517         if (!NT_STATUS_IS_OK(status)) {
13518                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13519                 goto done;
13520         }
13521         TALLOC_FREE(rec);
13522
13523         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13524         if (rec == NULL) {
13525                 d_fprintf(stderr, "second fetch_locked failed\n");
13526                 goto done;
13527         }
13528
13529         dbvalue = dbwrap_record_get_value(rec);
13530         if ((dbvalue.dsize != data.dsize)
13531             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13532                 d_fprintf(stderr, "Got wrong data back\n");
13533                 goto done;
13534         }
13535
13536         ret = true;
13537  done:
13538         TALLOC_FREE(rec);
13539         return ret;
13540 }
13541
13542 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13543 {
13544         int *count2 = (int *)private_data;
13545         (*count2)++;
13546         return 0;
13547 }
13548
13549 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13550 {
13551         int *count2 = (int *)private_data;
13552         (*count2)++;
13553         dbwrap_record_delete(rec);
13554         return 0;
13555 }
13556
13557 static bool run_local_rbtree(int dummy)
13558 {
13559         struct db_context *db;
13560         bool ret = false;
13561         int i;
13562         NTSTATUS status;
13563         int count = 0;
13564         int count2 = 0;
13565
13566         db = db_open_rbt(NULL);
13567
13568         if (db == NULL) {
13569                 d_fprintf(stderr, "db_open_rbt failed\n");
13570                 return false;
13571         }
13572
13573         if (!rbt_testflags(db, "firstkey", "firstval")) {
13574                 goto done;
13575         }
13576
13577         for (i = 0; i < 999; i++) {
13578                 char key[sizeof("key-9223372036854775807")];
13579                 char value[sizeof("value-9223372036854775807")];
13580
13581                 snprintf(key, sizeof(key), "key%ld", random());
13582                 snprintf(value, sizeof(value) ,"value%ld", random());
13583
13584                 if (!rbt_testval(db, key, value)) {
13585                         goto done;
13586                 }
13587
13588                 snprintf(value, sizeof(value) ,"value%ld", random());
13589
13590                 if (!rbt_testval(db, key, value)) {
13591                         goto done;
13592                 }
13593         }
13594
13595         ret = true;
13596         count = 0; count2 = 0;
13597         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13598                                       &count2, &count);
13599         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13600         if ((count != count2) || (count != 1000)) {
13601                 ret = false;
13602         }
13603         count = 0; count2 = 0;
13604         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13605                                  &count2, &count);
13606         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13607         if ((count != count2) || (count != 1000)) {
13608                 ret = false;
13609         }
13610         count = 0; count2 = 0;
13611         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13612                                       &count2, &count);
13613         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13614         if ((count != count2) || (count != 0)) {
13615                 ret = false;
13616         }
13617
13618  done:
13619         TALLOC_FREE(db);
13620         return ret;
13621 }
13622
13623
13624 /*
13625   local test for character set functions
13626
13627   This is a very simple test for the functionality in convert_string_error()
13628  */
13629 static bool run_local_convert_string(int dummy)
13630 {
13631         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13632         const char *test_strings[2] = { "March", "M\303\244rz" };
13633         char dst[7];
13634         int i;
13635
13636         for (i=0; i<2; i++) {
13637                 const char *str = test_strings[i];
13638                 int len = strlen(str);
13639                 size_t converted_size;
13640                 bool ret;
13641
13642                 memset(dst, 'X', sizeof(dst));
13643
13644                 /* first try with real source length */
13645                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13646                                            str, len,
13647                                            dst, sizeof(dst),
13648                                            &converted_size);
13649                 if (ret != true) {
13650                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13651                         goto failed;
13652                 }
13653
13654                 if (converted_size != len) {
13655                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13656                                   str, len, (int)converted_size);
13657                         goto failed;
13658                 }
13659
13660                 if (strncmp(str, dst, converted_size) != 0) {
13661                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13662                         goto failed;
13663                 }
13664
13665                 if (strlen(str) != converted_size) {
13666                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13667                                   (int)strlen(str), (int)converted_size);
13668                         goto failed;
13669                 }
13670
13671                 if (dst[converted_size] != 'X') {
13672                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13673                         goto failed;
13674                 }
13675
13676                 /* now with srclen==-1, this causes the nul to be
13677                  * converted too */
13678                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13679                                            str, -1,
13680                                            dst, sizeof(dst),
13681                                            &converted_size);
13682                 if (ret != true) {
13683                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13684                         goto failed;
13685                 }
13686
13687                 if (converted_size != len+1) {
13688                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13689                                   str, len, (int)converted_size);
13690                         goto failed;
13691                 }
13692
13693                 if (strncmp(str, dst, converted_size) != 0) {
13694                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13695                         goto failed;
13696                 }
13697
13698                 if (len+1 != converted_size) {
13699                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13700                                   len+1, (int)converted_size);
13701                         goto failed;
13702                 }
13703
13704                 if (dst[converted_size] != 'X') {
13705                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13706                         goto failed;
13707                 }
13708
13709         }
13710
13711
13712         TALLOC_FREE(tmp_ctx);
13713         return true;
13714 failed:
13715         TALLOC_FREE(tmp_ctx);
13716         return false;
13717 }
13718
13719 static bool run_local_string_to_sid(int dummy) {
13720         struct dom_sid sid;
13721
13722         if (string_to_sid(&sid, "S--1-5-32-545")) {
13723                 printf("allowing S--1-5-32-545\n");
13724                 return false;
13725         }
13726         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13727                 printf("allowing S-1-5-32-+545\n");
13728                 return false;
13729         }
13730         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")) {
13731                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13732                 return false;
13733         }
13734         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13735                 printf("allowing S-1-5-32-545-abc\n");
13736                 return false;
13737         }
13738         if (string_to_sid(&sid, "S-300-5-32-545")) {
13739                 printf("allowing S-300-5-32-545\n");
13740                 return false;
13741         }
13742         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13743                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13744                 return false;
13745         }
13746         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13747                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13748                 return false;
13749         }
13750         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13751                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13752                 return false;
13753         }
13754         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13755                 printf("could not parse S-1-5-32-545\n");
13756                 return false;
13757         }
13758         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13759                 struct dom_sid_buf buf;
13760                 printf("mis-parsed S-1-5-32-545 as %s\n",
13761                        dom_sid_str_buf(&sid, &buf));
13762                 return false;
13763         }
13764         return true;
13765 }
13766
13767 static bool sid_to_string_test(const char *expected) {
13768         char *str;
13769         bool res = true;
13770         struct dom_sid sid;
13771
13772         if (!string_to_sid(&sid, expected)) {
13773                 printf("could not parse %s\n", expected);
13774                 return false;
13775         }
13776
13777         str = dom_sid_string(NULL, &sid);
13778         if (strcmp(str, expected)) {
13779                 printf("Comparison failed (%s != %s)\n", str, expected);
13780                 res = false;
13781         }
13782         TALLOC_FREE(str);
13783         return res;
13784 }
13785
13786 static bool run_local_sid_to_string(int dummy) {
13787         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13788                 return false;
13789         if (!sid_to_string_test("S-1-545"))
13790                 return false;
13791         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13792                 return false;
13793         return true;
13794 }
13795
13796 static bool run_local_binary_to_sid(int dummy) {
13797         ssize_t ret;
13798         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13799         static const uint8_t good_binary_sid[] = {
13800                 0x1, /* revision number */
13801                 15, /* num auths */
13802                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13803                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13804                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13805                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13806                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13807                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13808                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13809                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13810                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13811                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13812                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13813                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13814                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13815                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13816                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13817                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13818         };
13819
13820         static const uint8_t long_binary_sid[] = {
13821                 0x1, /* revision number */
13822                 15, /* num auths */
13823                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13824                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13825                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13826                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13827                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13828                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13829                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13830                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13831                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13832                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13833                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13834                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13835                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13836                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13837                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13838                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13839                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13840                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13841                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13842         };
13843
13844         static const uint8_t long_binary_sid2[] = {
13845                 0x1, /* revision number */
13846                 32, /* num auths */
13847                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13848                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13849                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13850                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13851                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13852                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13853                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13854                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13855                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13856                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13857                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13858                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13859                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13860                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13861                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13862                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13863                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13864                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13865                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13866                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13867                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13868                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13869                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13870                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13871                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13872                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13873                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13874                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13875                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13876                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13877                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13878                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13879                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13880         };
13881
13882         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13883         if (ret == -1) {
13884                 return false;
13885         }
13886         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13887         if (ret != -1) {
13888                 return false;
13889         }
13890         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13891         if (ret != -1) {
13892                 return false;
13893         }
13894         return true;
13895 }
13896
13897 /* Split a path name into filename and stream name components. Canonicalise
13898  * such that an implicit $DATA token is always explicit.
13899  *
13900  * The "specification" of this function can be found in the
13901  * run_local_stream_name() function in torture.c, I've tried those
13902  * combinations against a W2k3 server.
13903  */
13904
13905 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13906                                        char **pbase, char **pstream)
13907 {
13908         char *base = NULL;
13909         char *stream = NULL;
13910         char *sname; /* stream name */
13911         const char *stype; /* stream type */
13912
13913         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13914
13915         sname = strchr_m(fname, ':');
13916
13917         if (sname == NULL) {
13918                 if (pbase != NULL) {
13919                         base = talloc_strdup(mem_ctx, fname);
13920                         NT_STATUS_HAVE_NO_MEMORY(base);
13921                 }
13922                 goto done;
13923         }
13924
13925         if (pbase != NULL) {
13926                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13927                 NT_STATUS_HAVE_NO_MEMORY(base);
13928         }
13929
13930         sname += 1;
13931
13932         stype = strchr_m(sname, ':');
13933
13934         if (stype == NULL) {
13935                 sname = talloc_strdup(mem_ctx, sname);
13936                 stype = "$DATA";
13937         }
13938         else {
13939                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13940                         /*
13941                          * If there is an explicit stream type, so far we only
13942                          * allow $DATA. Is there anything else allowed? -- vl
13943                          */
13944                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13945                         TALLOC_FREE(base);
13946                         return NT_STATUS_OBJECT_NAME_INVALID;
13947                 }
13948                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13949                 stype += 1;
13950         }
13951
13952         if (sname == NULL) {
13953                 TALLOC_FREE(base);
13954                 return NT_STATUS_NO_MEMORY;
13955         }
13956
13957         if (sname[0] == '\0') {
13958                 /*
13959                  * no stream name, so no stream
13960                  */
13961                 goto done;
13962         }
13963
13964         if (pstream != NULL) {
13965                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13966                 if (stream == NULL) {
13967                         TALLOC_FREE(sname);
13968                         TALLOC_FREE(base);
13969                         return NT_STATUS_NO_MEMORY;
13970                 }
13971                 /*
13972                  * upper-case the type field
13973                  */
13974                 (void)strupper_m(strchr_m(stream, ':')+1);
13975         }
13976
13977  done:
13978         if (pbase != NULL) {
13979                 *pbase = base;
13980         }
13981         if (pstream != NULL) {
13982                 *pstream = stream;
13983         }
13984         return NT_STATUS_OK;
13985 }
13986
13987 static bool test_stream_name(const char *fname, const char *expected_base,
13988                              const char *expected_stream,
13989                              NTSTATUS expected_status)
13990 {
13991         NTSTATUS status;
13992         char *base = NULL;
13993         char *stream = NULL;
13994
13995         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13996         if (!NT_STATUS_EQUAL(status, expected_status)) {
13997                 goto error;
13998         }
13999
14000         if (!NT_STATUS_IS_OK(status)) {
14001                 return true;
14002         }
14003
14004         if (base == NULL) goto error;
14005
14006         if (strcmp(expected_base, base) != 0) goto error;
14007
14008         if ((expected_stream != NULL) && (stream == NULL)) goto error;
14009         if ((expected_stream == NULL) && (stream != NULL)) goto error;
14010
14011         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14012                 goto error;
14013
14014         TALLOC_FREE(base);
14015         TALLOC_FREE(stream);
14016         return true;
14017
14018  error:
14019         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14020                   fname, expected_base ? expected_base : "<NULL>",
14021                   expected_stream ? expected_stream : "<NULL>",
14022                   nt_errstr(expected_status));
14023         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14024                   base ? base : "<NULL>", stream ? stream : "<NULL>",
14025                   nt_errstr(status));
14026         TALLOC_FREE(base);
14027         TALLOC_FREE(stream);
14028         return false;
14029 }
14030
14031 static bool run_local_stream_name(int dummy)
14032 {
14033         bool ret = true;
14034
14035         ret &= test_stream_name(
14036                 "bla", "bla", NULL, NT_STATUS_OK);
14037         ret &= test_stream_name(
14038                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14039         ret &= test_stream_name(
14040                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14041         ret &= test_stream_name(
14042                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14043         ret &= test_stream_name(
14044                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14045         ret &= test_stream_name(
14046                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14047         ret &= test_stream_name(
14048                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14049         ret &= test_stream_name(
14050                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14051
14052         return ret;
14053 }
14054
14055 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14056 {
14057         if (a.length != b.length) {
14058                 printf("a.length=%d != b.length=%d\n",
14059                        (int)a.length, (int)b.length);
14060                 return false;
14061         }
14062         if (memcmp(a.data, b.data, a.length) != 0) {
14063                 printf("a.data and b.data differ\n");
14064                 return false;
14065         }
14066         return true;
14067 }
14068
14069 static bool run_local_memcache(int dummy)
14070 {
14071         struct memcache *cache;
14072         DATA_BLOB k1, k2, k3, k4, k5;
14073         DATA_BLOB d1, d3;
14074         DATA_BLOB v1, v3;
14075
14076         TALLOC_CTX *mem_ctx;
14077         char *ptr1 = NULL;
14078         char *ptr2 = NULL;
14079         char *ptr3 = NULL;
14080
14081         char *str1, *str2;
14082         size_t size1, size2;
14083         bool ret = false;
14084
14085         mem_ctx = talloc_init("foo");
14086         if (mem_ctx == NULL) {
14087                 return false;
14088         }
14089
14090         /* STAT_CACHE TESTS */
14091
14092         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14093
14094         if (cache == NULL) {
14095                 printf("memcache_init failed\n");
14096                 return false;
14097         }
14098
14099         d1 = data_blob_const("d1", 2);
14100         d3 = data_blob_const("d3", 2);
14101
14102         k1 = data_blob_const("d1", 2);
14103         k2 = data_blob_const("d2", 2);
14104         k3 = data_blob_const("d3", 2);
14105         k4 = data_blob_const("d4", 2);
14106         k5 = data_blob_const("d5", 2);
14107
14108         memcache_add(cache, STAT_CACHE, k1, d1);
14109
14110         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14111                 printf("could not find k1\n");
14112                 return false;
14113         }
14114         if (!data_blob_equal(d1, v1)) {
14115                 return false;
14116         }
14117
14118         memcache_add(cache, STAT_CACHE, k1, d3);
14119
14120         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14121                 printf("could not find replaced k1\n");
14122                 return false;
14123         }
14124         if (!data_blob_equal(d3, v3)) {
14125                 return false;
14126         }
14127
14128         TALLOC_FREE(cache);
14129
14130         /* GETWD_CACHE TESTS */
14131         str1 = talloc_strdup(mem_ctx, "string1");
14132         if (str1 == NULL) {
14133                 return false;
14134         }
14135         ptr2 = str1; /* Keep an alias for comparison. */
14136
14137         str2 = talloc_strdup(mem_ctx, "string2");
14138         if (str2 == NULL) {
14139                 return false;
14140         }
14141
14142         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14143         if (cache == NULL) {
14144                 printf("memcache_init failed\n");
14145                 return false;
14146         }
14147
14148         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14149         /* str1 == NULL now. */
14150         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14151         if (ptr1 == NULL) {
14152                 printf("could not find k2\n");
14153                 return false;
14154         }
14155         if (ptr1 != ptr2) {
14156                 printf("fetch of k2 got wrong string\n");
14157                 return false;
14158         }
14159
14160         /* Add a blob to ensure k2 gets purged. */
14161         d3 = data_blob_talloc_zero(mem_ctx, 180);
14162         memcache_add(cache, STAT_CACHE, k3, d3);
14163
14164         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14165         if (ptr2 != NULL) {
14166                 printf("Did find k2, should have been purged\n");
14167                 return false;
14168         }
14169
14170         /*
14171          * Test that talloc size also is accounted in memcache and
14172          * causes purge of other object.
14173          */
14174
14175         str1 = talloc_zero_size(mem_ctx, 100);
14176         str2 = talloc_zero_size(mem_ctx, 100);
14177
14178         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14179         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14180
14181         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14182         if (ptr3 != NULL) {
14183                 printf("Did find k4, should have been purged\n");
14184                 return false;
14185         }
14186
14187         /*
14188          * Test that adding a duplicate non-talloced
14189          * key/value on top of a talloced key/value takes account
14190          * of the talloc_freed value size.
14191          */
14192         TALLOC_FREE(cache);
14193         TALLOC_FREE(mem_ctx);
14194
14195         mem_ctx = talloc_init("key_replace");
14196         if (mem_ctx == NULL) {
14197                 return false;
14198         }
14199
14200         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14201         if (cache == NULL) {
14202                 return false;
14203         }
14204
14205         /*
14206          * Add a 100 byte talloced string. This will
14207          * store a (4 or 8 byte) pointer and record the
14208          * total talloced size.
14209          */
14210         str1 = talloc_zero_size(mem_ctx, 100);
14211         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14212         /*
14213          * Now overwrite with a small talloced
14214          * value. This should fit in the existing size
14215          * and the total talloced size should be removed
14216          * from the cache size.
14217          */
14218         str1 = talloc_zero_size(mem_ctx, 2);
14219         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14220         /*
14221          * Now store a 20 byte string. If the
14222          * total talloced size wasn't accounted for
14223          * and removed in the overwrite, then this
14224          * will evict k4.
14225          */
14226         str2 = talloc_zero_size(mem_ctx, 20);
14227         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14228
14229         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14230         if (ptr3 == NULL) {
14231                 printf("Did not find k4, should not have been purged\n");
14232                 return false;
14233         }
14234
14235         TALLOC_FREE(cache);
14236         TALLOC_FREE(mem_ctx);
14237
14238         mem_ctx = talloc_init("foo");
14239         if (mem_ctx == NULL) {
14240                 return false;
14241         }
14242
14243         cache = memcache_init(NULL, 0);
14244         if (cache == NULL) {
14245                 return false;
14246         }
14247
14248         str1 = talloc_strdup(mem_ctx, "string1");
14249         if (str1 == NULL) {
14250                 return false;
14251         }
14252         str2 = talloc_strdup(mem_ctx, "string2");
14253         if (str2 == NULL) {
14254                 return false;
14255         }
14256         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14257                             data_blob_string_const("torture"), &str1);
14258         size1 = talloc_total_size(cache);
14259
14260         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14261                             data_blob_string_const("torture"), &str2);
14262         size2 = talloc_total_size(cache);
14263
14264         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14265
14266         if (size2 > size1) {
14267                 printf("memcache leaks memory!\n");
14268                 goto fail;
14269         }
14270
14271         ret = true;
14272  fail:
14273         TALLOC_FREE(cache);
14274         return ret;
14275 }
14276
14277 static void wbclient_done(struct tevent_req *req)
14278 {
14279         wbcErr wbc_err;
14280         struct winbindd_response *wb_resp;
14281         int *i = (int *)tevent_req_callback_data_void(req);
14282
14283         wbc_err = wb_trans_recv(req, req, &wb_resp);
14284         TALLOC_FREE(req);
14285         *i += 1;
14286         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14287 }
14288
14289 static bool run_wbclient_multi_ping(int dummy)
14290 {
14291         struct tevent_context *ev;
14292         struct wb_context **wb_ctx;
14293         struct winbindd_request wb_req;
14294         bool result = false;
14295         int i, j;
14296
14297         BlockSignals(True, SIGPIPE);
14298
14299         ev = tevent_context_init(talloc_tos());
14300         if (ev == NULL) {
14301                 goto fail;
14302         }
14303
14304         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14305         if (wb_ctx == NULL) {
14306                 goto fail;
14307         }
14308
14309         ZERO_STRUCT(wb_req);
14310         wb_req.cmd = WINBINDD_PING;
14311
14312         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14313
14314         for (i=0; i<torture_nprocs; i++) {
14315                 wb_ctx[i] = wb_context_init(ev, NULL);
14316                 if (wb_ctx[i] == NULL) {
14317                         goto fail;
14318                 }
14319                 for (j=0; j<torture_numops; j++) {
14320                         struct tevent_req *req;
14321                         req = wb_trans_send(ev, ev, wb_ctx[i],
14322                                             (j % 2) == 0, &wb_req);
14323                         if (req == NULL) {
14324                                 goto fail;
14325                         }
14326                         tevent_req_set_callback(req, wbclient_done, &i);
14327                 }
14328         }
14329
14330         i = 0;
14331
14332         while (i < torture_nprocs * torture_numops) {
14333                 tevent_loop_once(ev);
14334         }
14335
14336         result = true;
14337  fail:
14338         TALLOC_FREE(ev);
14339         return result;
14340 }
14341
14342 static bool dbtrans_inc(struct db_context *db)
14343 {
14344         struct db_record *rec;
14345         uint32_t val;
14346         bool ret = false;
14347         NTSTATUS status;
14348         TDB_DATA value;
14349
14350         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14351         if (rec == NULL) {
14352                 printf(__location__ "fetch_lock failed\n");
14353                 return false;
14354         }
14355
14356         value = dbwrap_record_get_value(rec);
14357
14358         if (value.dsize != sizeof(uint32_t)) {
14359                 printf(__location__ "value.dsize = %d\n",
14360                        (int)value.dsize);
14361                 goto fail;
14362         }
14363
14364         memcpy(&val, value.dptr, sizeof(val));
14365         val += 1;
14366
14367         status = dbwrap_record_store(
14368                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14369         if (!NT_STATUS_IS_OK(status)) {
14370                 printf(__location__ "store failed: %s\n",
14371                        nt_errstr(status));
14372                 goto fail;
14373         }
14374
14375         ret = true;
14376 fail:
14377         TALLOC_FREE(rec);
14378         return ret;
14379 }
14380
14381 static bool run_local_dbtrans(int dummy)
14382 {
14383         struct db_context *db;
14384         struct db_record *rec;
14385         NTSTATUS status;
14386         uint32_t initial;
14387         int res;
14388         TDB_DATA value;
14389
14390         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14391                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14392                      DBWRAP_FLAG_NONE);
14393         if (db == NULL) {
14394                 printf("Could not open transtest.db\n");
14395                 return false;
14396         }
14397
14398         res = dbwrap_transaction_start(db);
14399         if (res != 0) {
14400                 printf(__location__ "transaction_start failed\n");
14401                 return false;
14402         }
14403
14404         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14405         if (rec == NULL) {
14406                 printf(__location__ "fetch_lock failed\n");
14407                 return false;
14408         }
14409
14410         value = dbwrap_record_get_value(rec);
14411
14412         if (value.dptr == NULL) {
14413                 initial = 0;
14414                 status = dbwrap_record_store(
14415                         rec, make_tdb_data((uint8_t *)&initial,
14416                                            sizeof(initial)),
14417                         0);
14418                 if (!NT_STATUS_IS_OK(status)) {
14419                         printf(__location__ "store returned %s\n",
14420                                nt_errstr(status));
14421                         return false;
14422                 }
14423         }
14424
14425         TALLOC_FREE(rec);
14426
14427         res = dbwrap_transaction_commit(db);
14428         if (res != 0) {
14429                 printf(__location__ "transaction_commit failed\n");
14430                 return false;
14431         }
14432
14433         while (true) {
14434                 uint32_t val, val2;
14435                 int i;
14436
14437                 res = dbwrap_transaction_start(db);
14438                 if (res != 0) {
14439                         printf(__location__ "transaction_start failed\n");
14440                         break;
14441                 }
14442
14443                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14444                 if (!NT_STATUS_IS_OK(status)) {
14445                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14446                                nt_errstr(status));
14447                         break;
14448                 }
14449
14450                 for (i=0; i<10; i++) {
14451                         if (!dbtrans_inc(db)) {
14452                                 return false;
14453                         }
14454                 }
14455
14456                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14457                 if (!NT_STATUS_IS_OK(status)) {
14458                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14459                                nt_errstr(status));
14460                         break;
14461                 }
14462
14463                 if (val2 != val + 10) {
14464                         printf(__location__ "val=%d, val2=%d\n",
14465                                (int)val, (int)val2);
14466                         break;
14467                 }
14468
14469                 printf("val2=%d\r", val2);
14470
14471                 res = dbwrap_transaction_commit(db);
14472                 if (res != 0) {
14473                         printf(__location__ "transaction_commit failed\n");
14474                         break;
14475                 }
14476         }
14477
14478         TALLOC_FREE(db);
14479         return true;
14480 }
14481
14482 /*
14483  * Just a dummy test to be run under a debugger. There's no real way
14484  * to inspect the tevent_poll specific function from outside of
14485  * tevent_poll.c.
14486  */
14487
14488 static bool run_local_tevent_poll(int dummy)
14489 {
14490         struct tevent_context *ev;
14491         struct tevent_fd *fd1, *fd2;
14492         bool result = false;
14493
14494         ev = tevent_context_init_byname(NULL, "poll");
14495         if (ev == NULL) {
14496                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14497                 goto fail;
14498         }
14499
14500         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14501         if (fd1 == NULL) {
14502                 d_fprintf(stderr, "tevent_add_fd failed\n");
14503                 goto fail;
14504         }
14505         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14506         if (fd2 == NULL) {
14507                 d_fprintf(stderr, "tevent_add_fd failed\n");
14508                 goto fail;
14509         }
14510         TALLOC_FREE(fd2);
14511
14512         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14513         if (fd2 == NULL) {
14514                 d_fprintf(stderr, "tevent_add_fd failed\n");
14515                 goto fail;
14516         }
14517
14518         result = true;
14519 fail:
14520         TALLOC_FREE(ev);
14521         return result;
14522 }
14523
14524 static bool run_local_hex_encode_buf(int dummy)
14525 {
14526         char buf[17];
14527         uint8_t src[8];
14528         size_t i;
14529
14530         for (i=0; i<sizeof(src); i++) {
14531                 src[i] = i;
14532         }
14533         hex_encode_buf(buf, src, sizeof(src));
14534         if (strcmp(buf, "0001020304050607") != 0) {
14535                 return false;
14536         }
14537         hex_encode_buf(buf, NULL, 0);
14538         if (buf[0] != '\0') {
14539                 return false;
14540         }
14541         return true;
14542 }
14543
14544 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14545         "0.0.0.0",
14546         "::0",
14547         "1.2.3.1",
14548         "0.0.0.0",
14549         "0.0.0.0",
14550         "1.2.3.2",
14551         "1.2.3.3",
14552         "1.2.3.4",
14553         "1.2.3.5",
14554         "::0",
14555         "1.2.3.6",
14556         "1.2.3.7",
14557         "::0",
14558         "::0",
14559         "::0",
14560         "1.2.3.8",
14561         "1.2.3.9",
14562         "1.2.3.10",
14563         "1.2.3.11",
14564         "1.2.3.12",
14565         "1.2.3.13",
14566         "1001:1111:1111:1000:0:1111:1111:1111",
14567         "1.2.3.1",
14568         "1.2.3.2",
14569         "1.2.3.3",
14570         "1.2.3.12",
14571         "::0",
14572         "::0"
14573 };
14574
14575 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14576         "1.2.3.1",
14577         "1.2.3.2",
14578         "1.2.3.3",
14579         "1.2.3.4",
14580         "1.2.3.5",
14581         "1.2.3.6",
14582         "1.2.3.7",
14583         "1.2.3.8",
14584         "1.2.3.9",
14585         "1.2.3.10",
14586         "1.2.3.11",
14587         "1.2.3.12",
14588         "1.2.3.13",
14589         "1001:1111:1111:1000:0:1111:1111:1111"
14590 };
14591
14592 static bool run_local_remove_duplicate_addrs2(int dummy)
14593 {
14594         struct samba_sockaddr test_vector[28];
14595         size_t count, i;
14596
14597         /* Construct the sockaddr_storage test vector. */
14598         for (i = 0; i < 28; i++) {
14599                 struct addrinfo hints;
14600                 struct addrinfo *res = NULL;
14601                 int ret;
14602
14603                 memset(&hints, '\0', sizeof(hints));
14604                 hints.ai_flags = AI_NUMERICHOST;
14605                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14606                                 NULL,
14607                                 &hints,
14608                                 &res);
14609                 if (ret) {
14610                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14611                                 remove_duplicate_addrs2_test_strings_vector[i]);
14612                         return false;
14613                 }
14614                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14615                 memcpy(&test_vector[i].u.ss,
14616                         res->ai_addr,
14617                         res->ai_addrlen);
14618                 freeaddrinfo(res);
14619         }
14620
14621         count = remove_duplicate_addrs2(test_vector, i);
14622
14623         if (count != 14) {
14624                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14625                         count);
14626                 return false;
14627         }
14628
14629         for (i = 0; i < count; i++) {
14630                 char addr[INET6_ADDRSTRLEN];
14631
14632                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14633
14634                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14635                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14636                                 i,
14637                                 addr,
14638                                 remove_duplicate_addrs2_test_strings_result[i]);
14639                         return false;
14640                 }
14641         }
14642
14643         printf("run_local_remove_duplicate_addrs2: success\n");
14644         return true;
14645 }
14646
14647 static bool run_local_tdb_opener(int dummy)
14648 {
14649         TDB_CONTEXT *t;
14650         unsigned v = 0;
14651
14652         while (1) {
14653                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14654                              O_RDWR|O_CREAT, 0755);
14655                 if (t == NULL) {
14656                         perror("tdb_open failed");
14657                         return false;
14658                 }
14659                 tdb_close(t);
14660
14661                 v += 1;
14662                 printf("\r%u", v);
14663         }
14664         return true;
14665 }
14666
14667 static bool run_local_tdb_writer(int dummy)
14668 {
14669         TDB_CONTEXT *t;
14670         unsigned v = 0;
14671         TDB_DATA val;
14672
14673         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14674         if (t == 0) {
14675                 perror("tdb_open failed");
14676                 return 1;
14677         }
14678
14679         val.dptr = (uint8_t *)&v;
14680         val.dsize = sizeof(v);
14681
14682         while (1) {
14683                 TDB_DATA data;
14684                 int ret;
14685
14686                 ret = tdb_store(t, val, val, 0);
14687                 if (ret != 0) {
14688                         printf("%s\n", tdb_errorstr(t));
14689                 }
14690                 v += 1;
14691                 printf("\r%u", v);
14692
14693                 data = tdb_fetch(t, val);
14694                 if (data.dptr != NULL) {
14695                         SAFE_FREE(data.dptr);
14696                 }
14697         }
14698         return true;
14699 }
14700
14701 static bool run_local_canonicalize_path(int dummy)
14702 {
14703         const char *src[] = {
14704                         "/foo/..",
14705                         "/..",
14706                         "/foo/bar/../baz",
14707                         "/foo/././",
14708                         "/../foo",
14709                         ".././././",
14710                         ".././././../../../boo",
14711                         "./..",
14712                         "/",
14713                         "/../../",
14714                         "/foo/../",
14715                         "/./././",
14716                         "/./././.",
14717                         "/.../././.",
14718                         "/./././.foo",
14719                         "/./././.foo.",
14720                         "/./././foo.",
14721                         "/foo/bar/..",
14722                         "/foo/bar/../baz/",
14723                         "////////////////",
14724                         "/////////./././././.",
14725                         "/./.././../.boo/../baz",
14726                         "/a/component/path",
14727                         "/a/component/path/",
14728                         "/a/component/path/..",
14729                         "/a/component/../path/",
14730                         "///a/./././///component/../////path/",
14731                         NULL
14732                         };
14733         const char *dst[] = {
14734                         "/",
14735                         "/",
14736                         "/foo/baz",
14737                         "/foo",
14738                         "/foo",
14739                         "/",
14740                         "/boo",
14741                         "/",
14742                         "/",
14743                         "/",
14744                         "/",
14745                         "/",
14746                         "/",
14747                         "/...",
14748                         "/.foo",
14749                         "/.foo.",
14750                         "/foo.",
14751                         "/foo",
14752                         "/foo/baz",
14753                         "/",
14754                         "/",
14755                         "/baz",
14756                         "/a/component/path",
14757                         "/a/component/path",
14758                         "/a/component",
14759                         "/a/path",
14760                         "/a/path",
14761                         NULL
14762                         };
14763         unsigned int i;
14764
14765         for (i = 0; src[i] != NULL; i++) {
14766                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14767                 if (d == NULL) {
14768                         perror("talloc fail\n");
14769                         return false;
14770                 }
14771                 if (strcmp(d, dst[i]) != 0) {
14772                         d_fprintf(stderr,
14773                                 "canonicalize mismatch %s -> %s != %s",
14774                                 src[i], d, dst[i]);
14775                         return false;
14776                 }
14777                 talloc_free(d);
14778         }
14779         return true;
14780 }
14781 struct session_setup_nt1_truncated_state {
14782         uint16_t vwv[13];
14783         uint8_t bytes[20];
14784 };
14785
14786 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14787
14788 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14789                 TALLOC_CTX *mem_ctx,
14790                 struct tevent_context *ev,
14791                 struct smbXcli_conn *conn)
14792 {
14793         uint16_t *vwv = NULL;
14794         uint8_t *bytes = NULL;
14795         const char *pass = "12345678";
14796         const char *uname = "z";
14797         struct session_setup_nt1_truncated_state *state = NULL;
14798         struct tevent_req *req = NULL;
14799         struct tevent_req *subreq = NULL;
14800
14801         req = tevent_req_create(mem_ctx,
14802                                 &state,
14803                                 struct session_setup_nt1_truncated_state);
14804         if (req == NULL) {
14805                 return NULL;
14806         }
14807         vwv = &state->vwv[0];
14808         bytes = &state->bytes[0];
14809
14810         SCVAL(vwv+0,  0, 0xff);
14811         SCVAL(vwv+0,  1, 0);
14812         SSVAL(vwv+1,  0, 0);
14813         SSVAL(vwv+2,  0, 8192);
14814         SSVAL(vwv+3,  0, 2);
14815         SSVAL(vwv+4,  0, 1);
14816         SIVAL(vwv+5,  0, 0);
14817         SSVAL(vwv+7,  0, strlen(pass)); /* OEMPasswordLen */
14818         SSVAL(vwv+8,  0, 0); /* UnicodePasswordLen */
14819         SSVAL(vwv+9,  0, 0); /* reserved */
14820         SSVAL(vwv+10, 0, 0); /* reserved */
14821         SIVAL(vwv+11, 0, CAP_STATUS32);
14822
14823         memcpy(bytes, pass, strlen(pass));
14824         bytes += strlen(pass);
14825         memcpy(bytes, uname, strlen(uname)+1);
14826
14827         subreq = smb1cli_req_send(state, ev, conn,
14828                                   SMBsesssetupX,
14829                                   0, /*  additional_flags */
14830                                   0, /*  clear_flags */
14831                                   0, /*  additional_flags2 */
14832                                   0, /*  clear_flags2 */
14833                                   10000, /* timeout_msec */
14834                                   getpid(),
14835                                   NULL, /* tcon */
14836                                   NULL, /* session */
14837                                   13, /* wct */
14838                                   state->vwv,
14839                                   strlen(pass), /* Truncate length at password. */
14840                                   state->bytes);
14841         if (tevent_req_nomem(subreq, req)) {
14842                 return tevent_req_post(req, ev);
14843         }
14844         tevent_req_set_callback(subreq,
14845                                 smb1_session_setup_nt1_truncated_done,
14846                                 req);
14847         return req;
14848 }
14849
14850 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14851 {
14852         struct tevent_req *req =
14853                 tevent_req_callback_data(subreq,
14854                 struct tevent_req);
14855         struct session_setup_nt1_truncated_state *state =
14856                 tevent_req_data(req,
14857                 struct session_setup_nt1_truncated_state);
14858         NTSTATUS status;
14859         struct smb1cli_req_expected_response expected[] = {
14860         {
14861                 .status = NT_STATUS_OK,
14862                 .wct    = 3,
14863         },
14864         };
14865
14866         status = smb1cli_req_recv(subreq, state,
14867                                   NULL,
14868                                   NULL,
14869                                   NULL,
14870                                   NULL,
14871                                   NULL, /* pvwv_offset */
14872                                   NULL,
14873                                   NULL,
14874                                   NULL, /* pbytes_offset */
14875                                   NULL,
14876                                   expected, ARRAY_SIZE(expected));
14877         TALLOC_FREE(subreq);
14878         if (tevent_req_nterror(req, status)) {
14879                 return;
14880         }
14881         tevent_req_done(req);
14882 }
14883
14884 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14885 {
14886         return tevent_req_simple_recv_ntstatus(req);
14887 }
14888
14889 static bool run_smb1_truncated_sesssetup(int dummy)
14890 {
14891         struct tevent_context *ev;
14892         struct tevent_req *req;
14893         struct smbXcli_conn *conn;
14894         struct sockaddr_storage ss;
14895         NTSTATUS status;
14896         int fd;
14897         bool ok;
14898
14899         printf("Starting send truncated SMB1 sesssetup.\n");
14900
14901         ok = resolve_name(host, &ss, 0x20, true);
14902         if (!ok) {
14903                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14904                 return false;
14905         }
14906
14907         status = open_socket_out(&ss, 445, 10000, &fd);
14908         if (!NT_STATUS_IS_OK(status)) {
14909                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14910                           nt_errstr(status));
14911                 return false;
14912         }
14913
14914         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14915                                    NULL, 0, NULL);
14916         if (conn == NULL) {
14917                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14918                 return false;
14919         }
14920
14921         status = smbXcli_negprot(conn,
14922                                  0,
14923                                  PROTOCOL_NT1,
14924                                  PROTOCOL_NT1,
14925                                  NULL,
14926                                  NULL,
14927                                  NULL);
14928         if (!NT_STATUS_IS_OK(status)) {
14929                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14930                 return false;
14931         }
14932
14933         ev = samba_tevent_context_init(talloc_tos());
14934         if (ev == NULL) {
14935                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14936                 return false;
14937         }
14938
14939         req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14940         if (req == NULL) {
14941                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14942                 return false;
14943         }
14944
14945         ok = tevent_req_poll_ntstatus(req, ev, &status);
14946         if (!ok) {
14947                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14948                         nt_errstr(status));
14949                 return false;
14950         }
14951
14952         status = smb1_session_setup_nt1_truncated_recv(req);
14953         if (!NT_STATUS_IS_OK(status)) {
14954                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14955                           "%s, expected NT_STATUS_OK\n",
14956                           nt_errstr(status));
14957                 return false;
14958         }
14959
14960         TALLOC_FREE(conn);
14961         return true;
14962 }
14963
14964 struct smb1_negotiate_exit_state {
14965         int dummy;
14966 };
14967
14968 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14969
14970 static struct tevent_req *smb1_negotiate_exit_send(
14971                 TALLOC_CTX *mem_ctx,
14972                 struct tevent_context *ev,
14973                 struct smbXcli_conn *conn)
14974 {
14975         struct smb1_negotiate_exit_state *state = NULL;
14976         struct tevent_req *req = NULL;
14977         struct tevent_req *subreq = NULL;
14978
14979         req = tevent_req_create(mem_ctx,
14980                                 &state,
14981                                 struct smb1_negotiate_exit_state);
14982         if (req == NULL) {
14983                 return NULL;
14984         }
14985         subreq = smb1cli_req_send(state, ev, conn,
14986                                   SMBexit,
14987                                   0, /*  additional_flags */
14988                                   0, /*  clear_flags */
14989                                   0, /*  additional_flags2 */
14990                                   0, /*  clear_flags2 */
14991                                   10000, /* timeout_msec */
14992                                   getpid(),
14993                                   NULL, /* tcon */
14994                                   NULL, /* session */
14995                                   0, /* wct */
14996                                   NULL,
14997                                   0,
14998                                   NULL);
14999         if (tevent_req_nomem(subreq, req)) {
15000                 return tevent_req_post(req, ev);
15001         }
15002         tevent_req_set_callback(subreq,
15003                                 smb1_negotiate_exit_done,
15004                                 req);
15005         return req;
15006 }
15007
15008 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15009 {
15010         struct tevent_req *req =
15011                 tevent_req_callback_data(subreq,
15012                 struct tevent_req);
15013         struct smb1_negotiate_exit_state *state =
15014                 tevent_req_data(req,
15015                 struct smb1_negotiate_exit_state);
15016         NTSTATUS status;
15017         struct smb1cli_req_expected_response expected[] = {
15018         {
15019                 .status = NT_STATUS_OK,
15020                 .wct    = 0,
15021         },
15022         };
15023
15024         status = smb1cli_req_recv(subreq, state,
15025                                   NULL,
15026                                   NULL,
15027                                   NULL,
15028                                   NULL,
15029                                   NULL, /* pvwv_offset */
15030                                   NULL,
15031                                   NULL,
15032                                   NULL, /* pbytes_offset */
15033                                   NULL,
15034                                   expected, ARRAY_SIZE(expected));
15035         TALLOC_FREE(subreq);
15036         if (tevent_req_nterror(req, status)) {
15037                 return;
15038         }
15039         tevent_req_done(req);
15040 }
15041
15042 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15043 {
15044         return tevent_req_simple_recv_ntstatus(req);
15045 }
15046
15047 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15048                          struct tevent_context *ev,
15049                          struct smbXcli_conn *conn)
15050 {
15051         struct tevent_req *req;
15052         bool ok;
15053         NTSTATUS status;
15054         NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15055
15056         req = smb1_negotiate_exit_send(ev, ev, conn);
15057         if (req == NULL) {
15058                 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15059                 return false;
15060         }
15061
15062         ok = tevent_req_poll_ntstatus(req, ev, &status);
15063         if (!ok) {
15064                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15065                         nt_errstr(status));
15066                 return false;
15067         }
15068
15069         status = smb1_negotiate_exit_recv(req);
15070         if (!NT_STATUS_EQUAL(status, expected_status)) {
15071                 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15072                           "%s, expected ERRSRV, ERRinvnid\n",
15073                           nt_errstr(status));
15074                 return false;
15075         }
15076         return true;
15077 }
15078
15079 static bool run_smb1_negotiate_exit(int dummy)
15080 {
15081         struct tevent_context *ev;
15082         struct smbXcli_conn *conn;
15083         struct sockaddr_storage ss;
15084         NTSTATUS status;
15085         int fd;
15086         bool ok;
15087
15088         printf("Starting send SMB1 negotiate+exit.\n");
15089
15090         ok = resolve_name(host, &ss, 0x20, true);
15091         if (!ok) {
15092                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15093                 return false;
15094         }
15095
15096         status = open_socket_out(&ss, 445, 10000, &fd);
15097         if (!NT_STATUS_IS_OK(status)) {
15098                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15099                           nt_errstr(status));
15100                 return false;
15101         }
15102
15103         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15104                                    NULL, 0, NULL);
15105         if (conn == NULL) {
15106                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15107                 return false;
15108         }
15109
15110         status = smbXcli_negprot(conn,
15111                                  0,
15112                                  PROTOCOL_NT1,
15113                                  PROTOCOL_NT1,
15114                                  NULL,
15115                                  NULL,
15116                                  NULL);
15117         if (!NT_STATUS_IS_OK(status)) {
15118                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15119                 return false;
15120         }
15121
15122         ev = samba_tevent_context_init(talloc_tos());
15123         if (ev == NULL) {
15124                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15125                 return false;
15126         }
15127
15128         /*
15129          * Call do_smb1_exit twice to catch a server crash, the
15130          * server sends the first return code then crashes.
15131          */
15132         ok = do_smb1_exit(ev, ev, conn);
15133         if (!ok) {
15134                 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15135                 return false;
15136         }
15137         ok = do_smb1_exit(ev, ev, conn);
15138         if (!ok) {
15139                 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15140                 return false;
15141         }
15142
15143         TALLOC_FREE(conn);
15144         return true;
15145 }
15146
15147 static bool run_smb1_negotiate_tcon(int dummy)
15148 {
15149         struct cli_state *cli = NULL;
15150         uint16_t cnum = 0;
15151         uint16_t max_xmit = 0;
15152         NTSTATUS status;
15153
15154         printf("Starting send SMB1 negotiate+tcon.\n");
15155         cli = open_nbt_connection();
15156         if (cli == NULL) {
15157                 d_fprintf(stderr, "open_nbt_connection failed!\n");
15158                 return false;
15159         }
15160         smbXcli_conn_set_sockopt(cli->conn, sockops);
15161
15162         status = smbXcli_negprot(cli->conn,
15163                                  0,
15164                                  PROTOCOL_NT1,
15165                                  PROTOCOL_NT1,
15166                                  NULL,
15167                                  NULL,
15168                                  NULL);
15169         if (!NT_STATUS_IS_OK(status)) {
15170                 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15171                         nt_errstr(status));
15172                 return false;
15173         }
15174         status = cli_raw_tcon(cli,
15175                               share,
15176                               "",
15177                               "?????",
15178                               &max_xmit,
15179                               &cnum);
15180         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15181                 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15182                         "(should get NT_STATUS_ACCESS_DENIED)!\n",
15183                         nt_errstr(status));
15184                 return false;
15185         }
15186         return true;
15187 }
15188
15189 static bool run_ign_bad_negprot(int dummy)
15190 {
15191         struct tevent_context *ev;
15192         struct tevent_req *req;
15193         struct smbXcli_conn *conn;
15194         struct sockaddr_storage ss;
15195         NTSTATUS status;
15196         int fd;
15197         bool ok;
15198
15199         printf("starting ignore bad negprot\n");
15200
15201         ok = resolve_name(host, &ss, 0x20, true);
15202         if (!ok) {
15203                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15204                 return false;
15205         }
15206
15207         status = open_socket_out(&ss, 445, 10000, &fd);
15208         if (!NT_STATUS_IS_OK(status)) {
15209                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15210                           nt_errstr(status));
15211                 return false;
15212         }
15213
15214         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15215                                    NULL, 0, NULL);
15216         if (conn == NULL) {
15217                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15218                 return false;
15219         }
15220
15221         status = smbXcli_negprot(conn,
15222                                  0,
15223                                  PROTOCOL_CORE,
15224                                  PROTOCOL_CORE,
15225                                  NULL,
15226                                  NULL,
15227                                  NULL);
15228         if (NT_STATUS_IS_OK(status)) {
15229                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15230                 return false;
15231         }
15232
15233         ev = samba_tevent_context_init(talloc_tos());
15234         if (ev == NULL) {
15235                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15236                 return false;
15237         }
15238
15239         req = smb1cli_session_setup_nt1_send(
15240                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15241                 data_blob_null, data_blob_null, 0x40,
15242                 "Windows 2000 2195", "Windows 2000 5.0");
15243         if (req == NULL) {
15244                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15245                 return false;
15246         }
15247
15248         ok = tevent_req_poll_ntstatus(req, ev, &status);
15249         if (!ok) {
15250                 d_fprintf(stderr, "tevent_req_poll failed\n");
15251                 return false;
15252         }
15253
15254         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15255                                                 NULL, NULL);
15256         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15257                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15258                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
15259                           nt_errstr(status));
15260                 return false;
15261         }
15262
15263         TALLOC_FREE(conn);
15264
15265         printf("starting ignore bad negprot\n");
15266
15267         return true;
15268 }
15269
15270
15271 static double create_procs(bool (*fn)(int), bool *result)
15272 {
15273         int i, status;
15274         volatile pid_t *child_status;
15275         volatile bool *child_status_out;
15276         int synccount;
15277         int tries = 8;
15278         struct timeval start;
15279
15280         synccount = 0;
15281
15282         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15283         if (!child_status) {
15284                 printf("Failed to setup shared memory\n");
15285                 return -1;
15286         }
15287
15288         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15289         if (!child_status_out) {
15290                 printf("Failed to setup result status shared memory\n");
15291                 return -1;
15292         }
15293
15294         for (i = 0; i < torture_nprocs; i++) {
15295                 child_status[i] = 0;
15296                 child_status_out[i] = True;
15297         }
15298
15299         start = timeval_current();
15300
15301         for (i=0;i<torture_nprocs;i++) {
15302                 procnum = i;
15303                 if (fork() == 0) {
15304                         pid_t mypid = getpid();
15305                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15306
15307                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
15308
15309                         while (1) {
15310                                 if (torture_open_connection(&current_cli, i)) break;
15311                                 if (tries-- == 0) {
15312                                         printf("pid %d failed to start\n", (int)getpid());
15313                                         _exit(1);
15314                                 }
15315                                 smb_msleep(10); 
15316                         }
15317
15318                         child_status[i] = getpid();
15319
15320                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15321
15322                         child_status_out[i] = fn(i);
15323                         _exit(0);
15324                 }
15325         }
15326
15327         do {
15328                 synccount = 0;
15329                 for (i=0;i<torture_nprocs;i++) {
15330                         if (child_status[i]) synccount++;
15331                 }
15332                 if (synccount == torture_nprocs) break;
15333                 smb_msleep(10);
15334         } while (timeval_elapsed(&start) < 30);
15335
15336         if (synccount != torture_nprocs) {
15337                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15338                 *result = False;
15339                 return timeval_elapsed(&start);
15340         }
15341
15342         /* start the client load */
15343         start = timeval_current();
15344
15345         for (i=0;i<torture_nprocs;i++) {
15346                 child_status[i] = 0;
15347         }
15348
15349         printf("%d clients started\n", torture_nprocs);
15350
15351         for (i=0;i<torture_nprocs;i++) {
15352                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15353         }
15354
15355         printf("\n");
15356
15357         for (i=0;i<torture_nprocs;i++) {
15358                 if (!child_status_out[i]) {
15359                         *result = False;
15360                 }
15361         }
15362         return timeval_elapsed(&start);
15363 }
15364
15365 #define FLAG_MULTIPROC 1
15366
15367 static struct {
15368         const char *name;
15369         bool (*fn)(int);
15370         unsigned flags;
15371 } torture_ops[] = {
15372         {
15373                 .name = "FDPASS",
15374                 .fn   = run_fdpasstest,
15375         },
15376         {
15377                 .name = "LOCK1",
15378                 .fn   = run_locktest1,
15379         },
15380         {
15381                 .name = "LOCK2",
15382                 .fn   =  run_locktest2,
15383         },
15384         {
15385                 .name = "LOCK3",
15386                 .fn   =  run_locktest3,
15387         },
15388         {
15389                 .name = "LOCK4",
15390                 .fn   =  run_locktest4,
15391         },
15392         {
15393                 .name = "LOCK5",
15394                 .fn   =  run_locktest5,
15395         },
15396         {
15397                 .name = "LOCK6",
15398                 .fn   =  run_locktest6,
15399         },
15400         {
15401                 .name = "LOCK7",
15402                 .fn   =  run_locktest7,
15403         },
15404         {
15405                 .name = "LOCK8",
15406                 .fn   =  run_locktest8,
15407         },
15408         {
15409                 .name = "LOCK9A",
15410                 .fn   =  run_locktest9a,
15411         },
15412         {
15413                 .name = "LOCK9B",
15414                 .fn   =  run_locktest9b,
15415         },
15416         {
15417                 .name = "LOCK10",
15418                 .fn   =  run_locktest10,
15419         },
15420         {
15421                 .name = "LOCK11",
15422                 .fn   =  run_locktest11,
15423         },
15424         {
15425                 .name = "LOCK12",
15426                 .fn   =  run_locktest12,
15427         },
15428         {
15429                 .name = "LOCK13",
15430                 .fn   =  run_locktest13,
15431         },
15432         {
15433                 .name = "UNLINK",
15434                 .fn   = run_unlinktest,
15435         },
15436         {
15437                 .name = "BROWSE",
15438                 .fn   = run_browsetest,
15439         },
15440         {
15441                 .name = "ATTR",
15442                 .fn   =   run_attrtest,
15443         },
15444         {
15445                 .name = "TRANS2",
15446                 .fn   = run_trans2test,
15447         },
15448         {
15449                 .name  = "MAXFID",
15450                 .fn    = run_maxfidtest,
15451                 .flags = FLAG_MULTIPROC,
15452         },
15453         {
15454                 .name  = "TORTURE",
15455                 .fn    = run_torture,
15456                 .flags = FLAG_MULTIPROC,
15457         },
15458         {
15459                 .name  = "RANDOMIPC",
15460                 .fn    = run_randomipc,
15461         },
15462         {
15463                 .name  = "NEGNOWAIT",
15464                 .fn    = run_negprot_nowait,
15465         },
15466         {
15467                 .name  = "NBENCH",
15468                 .fn    =  run_nbench,
15469         },
15470         {
15471                 .name  = "NBENCH2",
15472                 .fn    = run_nbench2,
15473         },
15474         {
15475                 .name  = "OPLOCK1",
15476                 .fn    =  run_oplock1,
15477         },
15478         {
15479                 .name  = "OPLOCK2",
15480                 .fn    =  run_oplock2,
15481         },
15482         {
15483                 .name  = "OPLOCK4",
15484                 .fn    =  run_oplock4,
15485         },
15486 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15487         {
15488                 .name  = "OPLOCK5",
15489                 .fn    =  run_oplock5,
15490         },
15491 #endif
15492         {
15493                 .name  = "DIR",
15494                 .fn    =  run_dirtest,
15495         },
15496         {
15497                 .name  = "DIR1",
15498                 .fn    =  run_dirtest1,
15499         },
15500         {
15501                 .name  = "DIR-CREATETIME",
15502                 .fn    =  run_dir_createtime,
15503         },
15504         {
15505                 .name  = "DENY1",
15506                 .fn    =  torture_denytest1,
15507         },
15508         {
15509                 .name  = "DENY2",
15510                 .fn    =  torture_denytest2,
15511         },
15512         {
15513                 .name  = "TCON",
15514                 .fn    =  run_tcon_test,
15515         },
15516         {
15517                 .name  = "TCONDEV",
15518                 .fn    =  run_tcon_devtype_test,
15519         },
15520         {
15521                 .name  = "RW1",
15522                 .fn    =  run_readwritetest,
15523         },
15524         {
15525                 .name  = "RW2",
15526                 .fn    =  run_readwritemulti,
15527                 .flags = FLAG_MULTIPROC
15528         },
15529         {
15530                 .name  = "RW3",
15531                 .fn    =  run_readwritelarge,
15532         },
15533         {
15534                 .name  = "RW-SIGNING",
15535                 .fn    =  run_readwritelarge_signtest,
15536         },
15537         {
15538                 .name  = "OPEN",
15539                 .fn    = run_opentest,
15540         },
15541         {
15542                 .name  = "POSIX",
15543                 .fn    = run_simple_posix_open_test,
15544         },
15545         {
15546                 .name  = "POSIX-APPEND",
15547                 .fn    = run_posix_append,
15548         },
15549         {
15550                 .name  = "POSIX-SYMLINK-ACL",
15551                 .fn    = run_acl_symlink_test,
15552         },
15553         {
15554                 .name  = "POSIX-SYMLINK-EA",
15555                 .fn    = run_ea_symlink_test,
15556         },
15557         {
15558                 .name  = "POSIX-STREAM-DELETE",
15559                 .fn    = run_posix_stream_delete,
15560         },
15561         {
15562                 .name  = "POSIX-OFD-LOCK",
15563                 .fn    = run_posix_ofd_lock_test,
15564         },
15565         {
15566                 .name  = "POSIX-BLOCKING-LOCK",
15567                 .fn    = run_posix_blocking_lock,
15568         },
15569         {
15570                 .name  = "POSIX-MKDIR",
15571                 .fn    = run_posix_mkdir_test,
15572         },
15573         {
15574                 .name  = "POSIX-ACL-OPLOCK",
15575                 .fn    = run_posix_acl_oplock_test,
15576         },
15577         {
15578                 .name  = "POSIX-ACL-SHAREROOT",
15579                 .fn    = run_posix_acl_shareroot_test,
15580         },
15581         {
15582                 .name  = "POSIX-LS-WILDCARD",
15583                 .fn    = run_posix_ls_wildcard_test,
15584         },
15585         {
15586                 .name  = "POSIX-LS-SINGLE",
15587                 .fn    = run_posix_ls_single_test,
15588         },
15589         {
15590                 .name  = "POSIX-READLINK",
15591                 .fn    = run_posix_readlink_test,
15592         },
15593         {
15594                 .name  = "POSIX-STAT",
15595                 .fn    = run_posix_stat_test,
15596         },
15597         {
15598                 .name  = "POSIX-SYMLINK-PARENT",
15599                 .fn    = run_posix_symlink_parent_test,
15600         },
15601         {
15602                 .name  = "POSIX-SYMLINK-CHMOD",
15603                 .fn    = run_posix_symlink_chmod_test,
15604         },
15605         {
15606                 .name  = "POSIX-SYMLINK-RENAME",
15607                 .fn    = run_posix_symlink_rename_test,
15608         },
15609         {
15610                 .name  = "POSIX-DIR-DEFAULT-ACL",
15611                 .fn    = run_posix_dir_default_acl_test,
15612         },
15613         {
15614                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15615                 .fn    = run_posix_symlink_getpathinfo_test,
15616         },
15617         {
15618                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15619                 .fn    = run_posix_symlink_setpathinfo_test,
15620         },
15621         {
15622                 .name  = "WINDOWS-BAD-SYMLINK",
15623                 .fn    = run_symlink_open_test,
15624         },
15625         {
15626                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15627                 .fn    = run_smb1_wild_mangle_unlink_test,
15628         },
15629         {
15630                 .name  = "SMB1-WILD-MANGLE-RENAME",
15631                 .fn    = run_smb1_wild_mangle_rename_test,
15632         },
15633         {
15634                 .name  = "CASE-INSENSITIVE-CREATE",
15635                 .fn    = run_case_insensitive_create,
15636         },
15637         {
15638                 .name  = "ASYNC-ECHO",
15639                 .fn    = run_async_echo,
15640         },
15641         {
15642                 .name  = "UID-REGRESSION-TEST",
15643                 .fn    = run_uid_regression_test,
15644         },
15645         {
15646                 .name  = "SHORTNAME-TEST",
15647                 .fn    = run_shortname_test,
15648         },
15649         {
15650                 .name  = "ADDRCHANGE",
15651                 .fn    = run_addrchange,
15652         },
15653 #if 1
15654         {
15655                 .name  = "OPENATTR",
15656                 .fn    = run_openattrtest,
15657         },
15658 #endif
15659         {
15660                 .name  = "XCOPY",
15661                 .fn    = run_xcopy,
15662         },
15663         {
15664                 .name  = "RENAME",
15665                 .fn    = run_rename,
15666         },
15667         {
15668                 .name  = "RENAME-ACCESS",
15669                 .fn    = run_rename_access,
15670         },
15671         {
15672                 .name  = "OWNER-RIGHTS",
15673                 .fn    = run_owner_rights,
15674         },
15675         {
15676                 .name  = "DELETE",
15677                 .fn    = run_deletetest,
15678         },
15679         {
15680                 .name  = "DELETE-STREAM",
15681                 .fn    = run_delete_stream,
15682         },
15683         {
15684                 .name  = "DELETE-PRINT",
15685                 .fn    = run_delete_print_test,
15686         },
15687         {
15688                 .name  = "DELETE-LN",
15689                 .fn    = run_deletetest_ln,
15690         },
15691         {
15692                 .name  = "PROPERTIES",
15693                 .fn    = run_properties,
15694         },
15695         {
15696                 .name  = "MANGLE",
15697                 .fn    = torture_mangle,
15698         },
15699         {
15700                 .name  = "MANGLE1",
15701                 .fn    = run_mangle1,
15702         },
15703         {
15704                 .name  = "MANGLE-ILLEGAL",
15705                 .fn    = run_mangle_illegal,
15706         },
15707         {
15708                 .name  = "W2K",
15709                 .fn    = run_w2ktest,
15710         },
15711         {
15712                 .name  = "TRANS2SCAN",
15713                 .fn    = torture_trans2_scan,
15714         },
15715         {
15716                 .name  = "NTTRANSSCAN",
15717                 .fn    = torture_nttrans_scan,
15718         },
15719         {
15720                 .name  = "UTABLE",
15721                 .fn    = torture_utable,
15722         },
15723         {
15724                 .name  = "CASETABLE",
15725                 .fn    = torture_casetable,
15726         },
15727         {
15728                 .name  = "ERRMAPEXTRACT",
15729                 .fn    = run_error_map_extract,
15730         },
15731         {
15732                 .name  = "PIPE_NUMBER",
15733                 .fn    = run_pipe_number,
15734         },
15735         {
15736                 .name  = "TCON2",
15737                 .fn    =  run_tcon2_test,
15738         },
15739         {
15740                 .name  = "IOCTL",
15741                 .fn    =  torture_ioctl_test,
15742         },
15743         {
15744                 .name  = "CHKPATH",
15745                 .fn    =  torture_chkpath_test,
15746         },
15747         {
15748                 .name  = "FDSESS",
15749                 .fn    = run_fdsesstest,
15750         },
15751         {
15752                 .name  = "EATEST",
15753                 .fn    = run_eatest,
15754         },
15755         {
15756                 .name  = "SESSSETUP_BENCH",
15757                 .fn    = run_sesssetup_bench,
15758         },
15759         {
15760                 .name  = "CHAIN1",
15761                 .fn    = run_chain1,
15762         },
15763         {
15764                 .name  = "CHAIN2",
15765                 .fn    = run_chain2,
15766         },
15767         {
15768                 .name  = "CHAIN3",
15769                 .fn    = run_chain3,
15770         },
15771         {
15772                 .name  = "WINDOWS-WRITE",
15773                 .fn    = run_windows_write,
15774         },
15775         {
15776                 .name  = "LARGE_READX",
15777                 .fn    = run_large_readx,
15778         },
15779         {
15780                 .name  = "MSDFS-ATTRIBUTE",
15781                 .fn    = run_msdfs_attribute,
15782         },
15783         {
15784                 .name  = "NTTRANS-CREATE",
15785                 .fn    = run_nttrans_create,
15786         },
15787         {
15788                 .name  = "NTTRANS-FSCTL",
15789                 .fn    = run_nttrans_fsctl,
15790         },
15791         {
15792                 .name  = "CLI_ECHO",
15793                 .fn    = run_cli_echo,
15794         },
15795         {
15796                 .name  = "CLI_SPLICE",
15797                 .fn    = run_cli_splice,
15798         },
15799         {
15800                 .name  = "TLDAP",
15801                 .fn    = run_tldap,
15802         },
15803         {
15804                 .name  = "STREAMERROR",
15805                 .fn    = run_streamerror,
15806         },
15807         {
15808                 .name  = "NOTIFY-BENCH",
15809                 .fn    = run_notify_bench,
15810         },
15811         {
15812                 .name  = "NOTIFY-BENCH2",
15813                 .fn    = run_notify_bench2,
15814         },
15815         {
15816                 .name  = "NOTIFY-BENCH3",
15817                 .fn    = run_notify_bench3,
15818         },
15819         {
15820                 .name  = "BAD-NBT-SESSION",
15821                 .fn    = run_bad_nbt_session,
15822         },
15823         {
15824                 .name  = "IGN-BAD-NEGPROT",
15825                 .fn    = run_ign_bad_negprot,
15826         },
15827         {
15828                 .name  = "SMB-ANY-CONNECT",
15829                 .fn    = run_smb_any_connect,
15830         },
15831         {
15832                 .name  = "NOTIFY-ONLINE",
15833                 .fn    = run_notify_online,
15834         },
15835         {
15836                 .name  = "SMB2-BASIC",
15837                 .fn    = run_smb2_basic,
15838         },
15839         {
15840                 .name  = "SMB2-NEGPROT",
15841                 .fn    = run_smb2_negprot,
15842         },
15843         {
15844                 .name  = "SMB2-ANONYMOUS",
15845                 .fn    = run_smb2_anonymous,
15846         },
15847         {
15848                 .name  = "SMB2-SESSION-RECONNECT",
15849                 .fn    = run_smb2_session_reconnect,
15850         },
15851         {
15852                 .name  = "SMB2-TCON-DEPENDENCE",
15853                 .fn    = run_smb2_tcon_dependence,
15854         },
15855         {
15856                 .name  = "SMB2-MULTI-CHANNEL",
15857                 .fn    = run_smb2_multi_channel,
15858         },
15859         {
15860                 .name  = "SMB2-SESSION-REAUTH",
15861                 .fn    = run_smb2_session_reauth,
15862         },
15863         {
15864                 .name  = "SMB2-FTRUNCATE",
15865                 .fn    = run_smb2_ftruncate,
15866         },
15867         {
15868                 .name  = "SMB2-DIR-FSYNC",
15869                 .fn    = run_smb2_dir_fsync,
15870         },
15871         {
15872                 .name  = "SMB2-PATH-SLASH",
15873                 .fn    = run_smb2_path_slash,
15874         },
15875         {
15876                 .name  = "SMB1-SYSTEM-SECURITY",
15877                 .fn    = run_smb1_system_security,
15878         },
15879         {
15880                 .name  = "SMB2-SACL",
15881                 .fn    = run_smb2_sacl,
15882         },
15883         {
15884                 .name  = "SMB2-QUOTA1",
15885                 .fn    = run_smb2_quota1,
15886         },
15887         {
15888                 .name  = "SMB2-INVALID-PIPENAME",
15889                 .fn    = run_smb2_invalid_pipename,
15890         },
15891         {
15892                 .name  = "SMB2-STREAM-ACL",
15893                 .fn    = run_smb2_stream_acl,
15894         },
15895         {
15896                 .name  = "SMB2-LIST-DIR-ASYNC",
15897                 .fn    = run_list_dir_async_test,
15898         },
15899         {
15900                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15901                 .fn    = run_delete_on_close_non_empty,
15902         },
15903         {
15904                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15905                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15906         },
15907         {
15908                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15909                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15910         },
15911         {
15912                 .name  = "SMB2-DFS-PATHS",
15913                 .fn    = run_smb2_dfs_paths,
15914         },
15915         {
15916                 .name  = "SMB2-NON-DFS-SHARE",
15917                 .fn    = run_smb2_non_dfs_share,
15918         },
15919         {
15920                 .name  = "SMB2-DFS-SHARE-NON-DFS-PATH",
15921                 .fn    = run_smb2_dfs_share_non_dfs_path,
15922         },
15923         {
15924                 .name  = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15925                 .fn    = run_smb2_dfs_filename_leading_backslash,
15926         },
15927         {
15928                 .name  = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15929                 .fn    = run_smb2_pipe_read_async_disconnect,
15930         },
15931         {
15932                 .name  = "SMB1-TRUNCATED-SESSSETUP",
15933                 .fn    = run_smb1_truncated_sesssetup,
15934         },
15935         {
15936                 .name  = "SMB1-NEGOTIATE-EXIT",
15937                 .fn    = run_smb1_negotiate_exit,
15938         },
15939         {
15940                 .name  = "SMB1-NEGOTIATE-TCON",
15941                 .fn    = run_smb1_negotiate_tcon,
15942         },
15943         {
15944                 .name  = "SMB1-DFS-PATHS",
15945                 .fn    = run_smb1_dfs_paths,
15946         },
15947         {
15948                 .name  = "SMB1-DFS-SEARCH-PATHS",
15949                 .fn    = run_smb1_dfs_search_paths,
15950         },
15951         {
15952                 .name  = "SMB1-DFS-OPERATIONS",
15953                 .fn    = run_smb1_dfs_operations,
15954         },
15955         {
15956                 .name  = "SMB1-DFS-BADPATH",
15957                 .fn    = run_smb1_dfs_check_badpath,
15958         },
15959         {
15960                 .name  = "CLEANUP1",
15961                 .fn    = run_cleanup1,
15962         },
15963         {
15964                 .name  = "CLEANUP2",
15965                 .fn    = run_cleanup2,
15966         },
15967         {
15968                 .name  = "CLEANUP4",
15969                 .fn    = run_cleanup4,
15970         },
15971         {
15972                 .name  = "OPLOCK-CANCEL",
15973                 .fn    = run_oplock_cancel,
15974         },
15975         {
15976                 .name  = "PIDHIGH",
15977                 .fn    = run_pidhigh,
15978         },
15979         {
15980                 .name  = "LOCAL-SUBSTITUTE",
15981                 .fn    = run_local_substitute,
15982         },
15983         {
15984                 .name  = "LOCAL-GENCACHE",
15985                 .fn    = run_local_gencache,
15986         },
15987         {
15988                 .name  = "LOCAL-DBWRAP-WATCH1",
15989                 .fn    = run_dbwrap_watch1,
15990         },
15991         {
15992                 .name  = "LOCAL-DBWRAP-WATCH2",
15993                 .fn    = run_dbwrap_watch2,
15994         },
15995         {
15996                 .name  = "LOCAL-DBWRAP-WATCH3",
15997                 .fn    = run_dbwrap_watch3,
15998         },
15999         {
16000                 .name  = "LOCAL-DBWRAP-WATCH4",
16001                 .fn    = run_dbwrap_watch4,
16002         },
16003         {
16004                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
16005                 .fn    = run_dbwrap_do_locked1,
16006         },
16007         {
16008                 .name  = "LOCAL-MESSAGING-READ1",
16009                 .fn    = run_messaging_read1,
16010         },
16011         {
16012                 .name  = "LOCAL-MESSAGING-READ2",
16013                 .fn    = run_messaging_read2,
16014         },
16015         {
16016                 .name  = "LOCAL-MESSAGING-READ3",
16017                 .fn    = run_messaging_read3,
16018         },
16019         {
16020                 .name  = "LOCAL-MESSAGING-READ4",
16021                 .fn    = run_messaging_read4,
16022         },
16023         {
16024                 .name  = "LOCAL-MESSAGING-FDPASS1",
16025                 .fn    = run_messaging_fdpass1,
16026         },
16027         {
16028                 .name  = "LOCAL-MESSAGING-FDPASS2",
16029                 .fn    = run_messaging_fdpass2,
16030         },
16031         {
16032                 .name  = "LOCAL-MESSAGING-FDPASS2a",
16033                 .fn    = run_messaging_fdpass2a,
16034         },
16035         {
16036                 .name  = "LOCAL-MESSAGING-FDPASS2b",
16037                 .fn    = run_messaging_fdpass2b,
16038         },
16039         {
16040                 .name  = "LOCAL-MESSAGING-SEND-ALL",
16041                 .fn    = run_messaging_send_all,
16042         },
16043         {
16044                 .name  = "LOCAL-BASE64",
16045                 .fn    = run_local_base64,
16046         },
16047         {
16048                 .name  = "LOCAL-RBTREE",
16049                 .fn    = run_local_rbtree,
16050         },
16051         {
16052                 .name  = "LOCAL-MEMCACHE",
16053                 .fn    = run_local_memcache,
16054         },
16055         {
16056                 .name  = "LOCAL-STREAM-NAME",
16057                 .fn    = run_local_stream_name,
16058         },
16059         {
16060                 .name  = "LOCAL-STR-MATCH-MSWILD",
16061                 .fn    = run_str_match_mswild,
16062         },
16063         {
16064                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
16065                 .fn    = run_str_match_regex_sub1,
16066         },
16067         {
16068                 .name  = "WBCLIENT-MULTI-PING",
16069                 .fn    = run_wbclient_multi_ping,
16070         },
16071         {
16072                 .name  = "LOCAL-string_to_sid",
16073                 .fn    = run_local_string_to_sid,
16074         },
16075         {
16076                 .name  = "LOCAL-sid_to_string",
16077                 .fn    = run_local_sid_to_string,
16078         },
16079         {
16080                 .name  = "LOCAL-binary_to_sid",
16081                 .fn    = run_local_binary_to_sid,
16082         },
16083         {
16084                 .name  = "LOCAL-DBTRANS",
16085                 .fn    = run_local_dbtrans,
16086         },
16087         {
16088                 .name  = "LOCAL-TEVENT-POLL",
16089                 .fn    = run_local_tevent_poll,
16090         },
16091         {
16092                 .name  = "LOCAL-CONVERT-STRING",
16093                 .fn    = run_local_convert_string,
16094         },
16095         {
16096                 .name  = "LOCAL-CONV-AUTH-INFO",
16097                 .fn    = run_local_conv_auth_info,
16098         },
16099         {
16100                 .name  = "LOCAL-hex_encode_buf",
16101                 .fn    = run_local_hex_encode_buf,
16102         },
16103         {
16104                 .name  = "LOCAL-IDMAP-TDB-COMMON",
16105                 .fn    = run_idmap_tdb_common_test,
16106         },
16107         {
16108                 .name  = "LOCAL-remove_duplicate_addrs2",
16109                 .fn    = run_local_remove_duplicate_addrs2,
16110         },
16111         {
16112                 .name  = "local-tdb-opener",
16113                 .fn    = run_local_tdb_opener,
16114         },
16115         {
16116                 .name  = "local-tdb-writer",
16117                 .fn    = run_local_tdb_writer,
16118         },
16119         {
16120                 .name  = "LOCAL-DBWRAP-CTDB1",
16121                 .fn    = run_local_dbwrap_ctdb1,
16122         },
16123         {
16124                 .name  = "LOCAL-BENCH-PTHREADPOOL",
16125                 .fn    = run_bench_pthreadpool,
16126         },
16127         {
16128                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
16129                 .fn    = run_pthreadpool_tevent,
16130         },
16131         {
16132                 .name  = "LOCAL-G-LOCK1",
16133                 .fn    = run_g_lock1,
16134         },
16135         {
16136                 .name  = "LOCAL-G-LOCK2",
16137                 .fn    = run_g_lock2,
16138         },
16139         {
16140                 .name  = "LOCAL-G-LOCK3",
16141                 .fn    = run_g_lock3,
16142         },
16143         {
16144                 .name  = "LOCAL-G-LOCK4",
16145                 .fn    = run_g_lock4,
16146         },
16147         {
16148                 .name  = "LOCAL-G-LOCK4A",
16149                 .fn    = run_g_lock4a,
16150         },
16151         {
16152                 .name  = "LOCAL-G-LOCK5",
16153                 .fn    = run_g_lock5,
16154         },
16155         {
16156                 .name  = "LOCAL-G-LOCK6",
16157                 .fn    = run_g_lock6,
16158         },
16159         {
16160                 .name  = "LOCAL-G-LOCK7",
16161                 .fn    = run_g_lock7,
16162         },
16163         {
16164                 .name  = "LOCAL-G-LOCK8",
16165                 .fn    = run_g_lock8,
16166         },
16167         {
16168                 .name  = "LOCAL-G-LOCK-PING-PONG",
16169                 .fn    = run_g_lock_ping_pong,
16170         },
16171         {
16172                 .name  = "LOCAL-CANONICALIZE-PATH",
16173                 .fn    = run_local_canonicalize_path,
16174         },
16175         {
16176                 .name  = "LOCAL-NAMEMAP-CACHE1",
16177                 .fn    = run_local_namemap_cache1,
16178         },
16179         {
16180                 .name  = "LOCAL-IDMAP-CACHE1",
16181                 .fn    = run_local_idmap_cache1,
16182         },
16183         {
16184                 .name  = "qpathinfo-bufsize",
16185                 .fn    = run_qpathinfo_bufsize,
16186         },
16187         {
16188                 .name  = "hide-new-files-timeout",
16189                 .fn    = run_hidenewfiles,
16190         },
16191         {
16192                 .name  = "hide-new-files-timeout-showdirs",
16193                 .fn    = run_hidenewfiles_showdirs,
16194         },
16195 #ifdef CLUSTER_SUPPORT
16196         {
16197                 .name  = "ctdbd-conn1",
16198                 .fn    = run_ctdbd_conn1,
16199         },
16200 #endif
16201         {
16202                 .name  = "readdir-timestamp",
16203                 .fn    = run_readdir_timestamp,
16204         },
16205         {
16206                 .name  = "rpc-scale",
16207                 .fn    = run_rpc_scale,
16208         },
16209         {
16210                 .name  = "LOCAL-TDB-VALIDATE",
16211                 .fn    = run_tdb_validate,
16212         },
16213         {
16214                 .name = NULL,
16215         },
16216 };
16217
16218 /****************************************************************************
16219 run a specified test or "ALL"
16220 ****************************************************************************/
16221 static bool run_test(const char *name)
16222 {
16223         bool ret = True;
16224         bool result = True;
16225         bool found = False;
16226         int i;
16227         double t;
16228         if (strequal(name,"ALL")) {
16229                 for (i=0;torture_ops[i].name;i++) {
16230                         run_test(torture_ops[i].name);
16231                 }
16232                 found = True;
16233         }
16234
16235         for (i=0;torture_ops[i].name;i++) {
16236                 fstr_sprintf(randomfname, "\\XX%x", 
16237                          (unsigned)random());
16238
16239                 if (strequal(name, torture_ops[i].name)) {
16240                         found = True;
16241                         printf("Running %s\n", name);
16242                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
16243                                 t = create_procs(torture_ops[i].fn, &result);
16244                                 if (!result) { 
16245                                         ret = False;
16246                                         printf("TEST %s FAILED!\n", name);
16247                                 }
16248                         } else {
16249                                 struct timeval start;
16250                                 start = timeval_current();
16251                                 if (!torture_ops[i].fn(0)) {
16252                                         ret = False;
16253                                         printf("TEST %s FAILED!\n", name);
16254                                 }
16255                                 t = timeval_elapsed(&start);
16256                         }
16257                         printf("%s took %g secs\n\n", name, t);
16258                 }
16259         }
16260
16261         if (!found) {
16262                 printf("Did not find a test named %s\n", name);
16263                 ret = False;
16264         }
16265
16266         return ret;
16267 }
16268
16269
16270 static void usage(void)
16271 {
16272         int i;
16273
16274         printf("WARNING samba4 test suite is much more complete nowadays.\n");
16275         printf("Please use samba4 torture.\n\n");
16276
16277         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16278
16279         printf("\t-d debuglevel\n");
16280         printf("\t-U user%%pass\n");
16281         printf("\t-k                    use kerberos\n");
16282         printf("\t-N numprocs\n");
16283         printf("\t-n my_netbios_name\n");
16284         printf("\t-W workgroup\n");
16285         printf("\t-o num_operations\n");
16286         printf("\t-O socket_options\n");
16287         printf("\t-m maximum protocol\n");
16288         printf("\t-L use oplocks\n");
16289         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
16290         printf("\t-A showall\n");
16291         printf("\t-p port\n");
16292         printf("\t-s seed\n");
16293         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
16294         printf("\t-f filename           filename to test\n");
16295         printf("\t-e                    encrypt\n");
16296         printf("\n\n");
16297
16298         printf("tests are:");
16299         for (i=0;torture_ops[i].name;i++) {
16300                 printf(" %s", torture_ops[i].name);
16301         }
16302         printf("\n");
16303
16304         printf("default test is ALL\n");
16305
16306         exit(1);
16307 }
16308
16309 /****************************************************************************
16310   main program
16311 ****************************************************************************/
16312  int main(int argc,char *argv[])
16313 {
16314         int opt, i;
16315         char *p;
16316         int gotuser = 0;
16317         int gotpass = 0;
16318         bool correct = True;
16319         TALLOC_CTX *frame = talloc_stackframe();
16320         int seed = time(NULL);
16321         struct loadparm_context *lp_ctx = NULL;
16322
16323 #ifdef HAVE_SETBUFFER
16324         setbuffer(stdout, NULL, 0);
16325 #endif
16326
16327         setup_logging("smbtorture", DEBUG_STDOUT);
16328
16329         smb_init_locale();
16330         fault_setup();
16331
16332         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16333         if (lp_ctx == NULL) {
16334                 fprintf(stderr,
16335                         "Failed to initialise the global parameter structure.\n");
16336                 return 1;
16337         }
16338
16339         if (is_default_dyn_CONFIGFILE()) {
16340                 if(getenv("SMB_CONF_PATH")) {
16341                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16342                 }
16343         }
16344         lp_load_global(get_dyn_CONFIGFILE());
16345         load_interfaces();
16346
16347         if (argc < 2) {
16348                 usage();
16349         }
16350
16351         for(p = argv[1]; *p; p++)
16352           if(*p == '\\')
16353             *p = '/';
16354
16355         if (strncmp(argv[1], "//", 2)) {
16356                 usage();
16357         }
16358
16359         fstrcpy(host, &argv[1][2]);
16360         p = strchr_m(&host[2],'/');
16361         if (!p) {
16362                 usage();
16363         }
16364         *p = 0;
16365         fstrcpy(share, p+1);
16366
16367         fstrcpy(myname, get_myname(talloc_tos()));
16368         if (!*myname) {
16369                 fprintf(stderr, "Failed to get my hostname.\n");
16370                 return 1;
16371         }
16372
16373         if (*username == 0 && getenv("LOGNAME")) {
16374           fstrcpy(username,getenv("LOGNAME"));
16375         }
16376
16377         argc--;
16378         argv++;
16379
16380         fstrcpy(workgroup, lp_workgroup());
16381
16382         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16383                != EOF) {
16384                 switch (opt) {
16385                 case 'p':
16386                         port_to_use = atoi(optarg);
16387                         break;
16388                 case 's':
16389                         seed = atoi(optarg);
16390                         break;
16391                 case 'W':
16392                         fstrcpy(workgroup,optarg);
16393                         break;
16394                 case 'm':
16395                         lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16396                         break;
16397                 case 'N':
16398                         torture_nprocs = atoi(optarg);
16399                         break;
16400                 case 'o':
16401                         torture_numops = atoi(optarg);
16402                         break;
16403                 case 'd':
16404                         lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16405                         break;
16406                 case 'O':
16407                         sockops = optarg;
16408                         break;
16409                 case 'L':
16410                         use_oplocks = True;
16411                         break;
16412                 case 'l':
16413                         local_path = optarg;
16414                         break;
16415                 case 'A':
16416                         torture_showall = True;
16417                         break;
16418                 case 'n':
16419                         fstrcpy(myname, optarg);
16420                         break;
16421                 case 'c':
16422                         client_txt = optarg;
16423                         break;
16424                 case 'e':
16425                         do_encrypt = true;
16426                         break;
16427                 case 'k':
16428 #ifdef HAVE_KRB5
16429                         use_kerberos = True;
16430 #else
16431                         d_printf("No kerberos support compiled in\n");
16432                         exit(1);
16433 #endif
16434                         break;
16435                 case 'U':
16436                         gotuser = 1;
16437                         fstrcpy(username,optarg);
16438                         p = strchr_m(username,'%');
16439                         if (p) {
16440                                 *p = 0;
16441                                 fstrcpy(password, p+1);
16442                                 gotpass = 1;
16443                         }
16444                         break;
16445                 case 'b':
16446                         fstrcpy(multishare_conn_fname, optarg);
16447                         use_multishare_conn = True;
16448                         break;
16449                 case 'B':
16450                         torture_blocksize = atoi(optarg);
16451                         break;
16452                 case 'f':
16453                         test_filename = SMB_STRDUP(optarg);
16454                         break;
16455                 default:
16456                         printf("Unknown option %c (%d)\n", (char)opt, opt);
16457                         usage();
16458                 }
16459         }
16460
16461         d_printf("using seed %d\n", seed);
16462
16463         srandom(seed);
16464
16465         if(use_kerberos && !gotuser) gotpass = True;
16466
16467         while (!gotpass) {
16468                 char pwd[256] = {0};
16469                 int rc;
16470
16471                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16472                 if (rc == 0) {
16473                         fstrcpy(password, pwd);
16474                         gotpass = 1;
16475                 }
16476         }
16477
16478         printf("host=%s share=%s user=%s myname=%s\n", 
16479                host, share, username, myname);
16480
16481         torture_creds = cli_session_creds_init(frame,
16482                                                username,
16483                                                workgroup,
16484                                                NULL, /* realm */
16485                                                password,
16486                                                use_kerberos,
16487                                                false, /* fallback_after_kerberos */
16488                                                false, /* use_ccache */
16489                                                false); /* password_is_nt_hash */
16490         if (torture_creds == NULL) {
16491                 d_printf("cli_session_creds_init() failed.\n");
16492                 exit(1);
16493         }
16494
16495         if (argc == optind) {
16496                 correct = run_test("ALL");
16497         } else {
16498                 for (i=optind;i<argc;i++) {
16499                         if (!run_test(argv[i])) {
16500                                 correct = False;
16501                         }
16502                 }
16503         }
16504
16505         TALLOC_FREE(frame);
16506
16507         if (correct) {
16508                 return(0);
16509         } else {
16510                 return(1);
16511         }
16512 }