s3:torture: Remove trailing spaces in torture.c
[samba.git] / source3 / torture / torture.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "tldap_tls_connect.h"
31 #include "../librpc/gen_ndr/svcctl.h"
32 #include "../lib/util/memcache.h"
33 #include "nsswitch/winbind_client.h"
34 #include "dbwrap/dbwrap.h"
35 #include "dbwrap/dbwrap_open.h"
36 #include "dbwrap/dbwrap_rbt.h"
37 #include "async_smb.h"
38 #include "libsmb/libsmb.h"
39 #include "libsmb/clirap.h"
40 #include "trans2.h"
41 #include "libsmb/nmblib.h"
42 #include "../lib/util/tevent_ntstatus.h"
43 #include "util_tdb.h"
44 #include "../libcli/smb/read_smb.h"
45 #include "../libcli/smb/smbXcli_base.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "lib/util/base64.h"
48 #include "lib/util/time.h"
49 #include "lib/gencache.h"
50 #include "lib/util/sys_rw.h"
51 #include "lib/util/asn1.h"
52 #include "lib/util/util_file.h"
53 #include "lib/param/param.h"
54 #include "auth/gensec/gensec.h"
55 #include "lib/util/string_wrappers.h"
56 #include "source3/lib/substitute.h"
57 #include "ads.h"
58
59 #include <gnutls/gnutls.h>
60 #include <gnutls/crypto.h>
61
62 extern char *optarg;
63 extern int optind;
64
65 fstring host, workgroup, share, password, username, myname;
66 struct cli_credentials *torture_creds;
67 static const char *sockops="TCP_NODELAY";
68 int torture_nprocs=1;
69 static int port_to_use=0;
70 int torture_numops=100;
71 int torture_blocksize=1024*1024;
72 static int procnum; /* records process count number when forking */
73 static struct cli_state *current_cli;
74 static fstring randomfname;
75 static bool use_oplocks;
76 static bool use_level_II_oplocks;
77 static const char *client_txt = "client_oplocks.txt";
78 static bool disable_spnego;
79 static bool use_kerberos;
80 static bool force_dos_errors;
81 static fstring multishare_conn_fname;
82 static bool use_multishare_conn = False;
83 static bool do_encrypt;
84 static const char *local_path = NULL;
85 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
86 char *test_filename;
87
88 bool torture_showall = False;
89
90 static double create_procs(bool (*fn)(int), bool *result);
91
92 /********************************************************************
93  Ensure a connection is encrypted.
94 ********************************************************************/
95
96 static bool force_cli_encryption(struct cli_state *c,
97                         const char *sharename)
98 {
99         uint16_t major, minor;
100         uint32_t caplow, caphigh;
101         NTSTATUS status;
102
103         if (!SERVER_HAS_UNIX_CIFS(c)) {
104                 d_printf("Encryption required and "
105                         "server that doesn't support "
106                         "UNIX extensions - failing connect\n");
107                         return false;
108         }
109
110         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
111                                              &caphigh);
112         if (!NT_STATUS_IS_OK(status)) {
113                 d_printf("Encryption required and "
114                         "can't get UNIX CIFS extensions "
115                         "version from server: %s\n", nt_errstr(status));
116                 return false;
117         }
118
119         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
120                 d_printf("Encryption required and "
121                         "share %s doesn't support "
122                         "encryption.\n", sharename);
123                 return false;
124         }
125
126         status = cli_smb1_setup_encryption(c, torture_creds);
127         if (!NT_STATUS_IS_OK(status)) {
128                 d_printf("Encryption required and "
129                         "setup failed with error %s.\n",
130                         nt_errstr(status));
131                 return false;
132         }
133
134         return true;
135 }
136
137
138 static struct cli_state *open_nbt_connection(void)
139 {
140         struct cli_state *c;
141         NTSTATUS status;
142         int flags = 0;
143
144         if (disable_spnego) {
145                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
146         }
147
148         if (use_oplocks) {
149                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
150         }
151
152         if (use_level_II_oplocks) {
153                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
154         }
155
156         if (force_dos_errors) {
157                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
158         }
159
160         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
161                                 signing_state, flags, &c);
162         if (!NT_STATUS_IS_OK(status)) {
163                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
164                 return NULL;
165         }
166
167         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
168
169         return c;
170 }
171
172 /****************************************************************************
173  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
174 ****************************************************************************/
175
176 static bool cli_bad_session_request(int fd,
177                          struct nmb_name *calling, struct nmb_name *called)
178 {
179         TALLOC_CTX *frame;
180         uint8_t len_buf[4];
181         struct iovec iov[3];
182         ssize_t len;
183         uint8_t *inbuf;
184         int err;
185         bool ret = false;
186         uint8_t message_type;
187         uint8_t error;
188         struct tevent_context *ev;
189         struct tevent_req *req;
190
191         frame = talloc_stackframe();
192
193         iov[0].iov_base = len_buf;
194         iov[0].iov_len  = sizeof(len_buf);
195
196         /* put in the destination name */
197
198         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
199                                       called->name_type);
200         if (iov[1].iov_base == NULL) {
201                 goto fail;
202         }
203         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
204                                   talloc_get_size(iov[1].iov_base));
205
206         /* and my name */
207
208         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
209                                       calling->name_type);
210         if (iov[2].iov_base == NULL) {
211                 goto fail;
212         }
213         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
214                                   talloc_get_size(iov[2].iov_base));
215
216         /* Deliberately corrupt the name len (first byte) */
217         *((uint8_t *)iov[2].iov_base) = 100;
218
219         /* send a session request (RFC 1002) */
220         /* setup the packet length
221          * Remove four bytes from the length count, since the length
222          * field in the NBT Session Service header counts the number
223          * of bytes which follow.  The cli_send_smb() function knows
224          * about this and accounts for those four bytes.
225          * CRH.
226          */
227
228         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
229         SCVAL(len_buf,0,0x81);
230
231         len = write_data_iov(fd, iov, 3);
232         if (len == -1) {
233                 goto fail;
234         }
235
236         ev = samba_tevent_context_init(frame);
237         if (ev == NULL) {
238                 goto fail;
239         }
240         req = read_smb_send(frame, ev, fd);
241         if (req == NULL) {
242                 goto fail;
243         }
244         if (!tevent_req_poll(req, ev)) {
245                 goto fail;
246         }
247         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
248         if (len == -1) {
249                 errno = err;
250                 goto fail;
251         }
252         TALLOC_FREE(ev);
253
254         message_type = CVAL(inbuf, 0);
255         if (message_type != 0x83) {
256                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
257                           message_type);
258                 goto fail;
259         }
260
261         if (smb_len(inbuf) != 1) {
262                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
263                           (int)smb_len(inbuf));
264                 goto fail;
265         }
266
267         error = CVAL(inbuf, 4);
268         if (error !=  0x82) {
269                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
270                           (int)error);
271                 goto fail;
272         }
273
274         ret = true;
275 fail:
276         TALLOC_FREE(frame);
277         return ret;
278 }
279
280 /* Insert a NULL at the first separator of the given path and return a pointer
281  * to the remainder of the string.
282  */
283 static char *
284 terminate_path_at_separator(char * path)
285 {
286         char * p;
287
288         if (!path) {
289                 return NULL;
290         }
291
292         if ((p = strchr_m(path, '/'))) {
293                 *p = '\0';
294                 return p + 1;
295         }
296
297         if ((p = strchr_m(path, '\\'))) {
298                 *p = '\0';
299                 return p + 1;
300         }
301
302         /* No separator. */
303         return NULL;
304 }
305
306 /*
307   parse a //server/share type UNC name
308 */
309 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
310                       char **hostname, char **sharename)
311 {
312         char *p;
313
314         *hostname = *sharename = NULL;
315
316         if (strncmp(unc_name, "\\\\", 2) &&
317             strncmp(unc_name, "//", 2)) {
318                 return False;
319         }
320
321         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
322         p = terminate_path_at_separator(*hostname);
323
324         if (p && *p) {
325                 *sharename = talloc_strdup(mem_ctx, p);
326                 terminate_path_at_separator(*sharename);
327         }
328
329         if (*hostname && *sharename) {
330                 return True;
331         }
332
333         TALLOC_FREE(*hostname);
334         TALLOC_FREE(*sharename);
335         return False;
336 }
337
338 static bool torture_open_connection_share(struct cli_state **c,
339                                    const char *hostname,
340                                    const char *sharename,
341                                    int flags)
342 {
343         NTSTATUS status;
344
345         status = cli_full_connection_creds(c,
346                                            myname,
347                                            hostname,
348                                            NULL, /* dest_ss */
349                                            port_to_use,
350                                            sharename,
351                                            "?????",
352                                            torture_creds,
353                                            flags);
354         if (!NT_STATUS_IS_OK(status)) {
355                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
356                         hostname, sharename, port_to_use, nt_errstr(status));
357                 return False;
358         }
359
360         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
361
362         if (do_encrypt) {
363                 return force_cli_encryption(*c,
364                                         sharename);
365         }
366         return True;
367 }
368
369 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
370 {
371         char **unc_list = NULL;
372         int num_unc_names = 0;
373         bool result;
374
375         if (use_multishare_conn==True) {
376                 char *h, *s;
377                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
378                 if (!unc_list || num_unc_names <= 0) {
379                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
380                         exit(1);
381                 }
382
383                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
384                                       NULL, &h, &s)) {
385                         printf("Failed to parse UNC name %s\n",
386                                unc_list[conn_index % num_unc_names]);
387                         TALLOC_FREE(unc_list);
388                         exit(1);
389                 }
390
391                 result = torture_open_connection_share(c, h, s, flags);
392
393                 /* h, s were copied earlier */
394                 TALLOC_FREE(unc_list);
395                 return result;
396         }
397
398         return torture_open_connection_share(c, host, share, flags);
399 }
400
401 bool torture_open_connection(struct cli_state **c, int conn_index)
402 {
403         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
404
405         if (use_oplocks) {
406                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
407         }
408         if (use_level_II_oplocks) {
409                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
410         }
411
412         return torture_open_connection_flags(c, conn_index, flags);
413 }
414
415 bool torture_init_connection(struct cli_state **pcli)
416 {
417         struct cli_state *cli;
418
419         cli = open_nbt_connection();
420         if (cli == NULL) {
421                 return false;
422         }
423
424         *pcli = cli;
425         return true;
426 }
427
428 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
429 {
430         uint16_t old_vuid = cli_state_get_uid(cli);
431         NTSTATUS status;
432         bool ret;
433
434         cli_state_set_uid(cli, 0);
435         status = cli_session_setup_creds(cli, torture_creds);
436         ret = NT_STATUS_IS_OK(status);
437         *new_vuid = cli_state_get_uid(cli);
438         cli_state_set_uid(cli, old_vuid);
439         return ret;
440 }
441
442
443 bool torture_close_connection(struct cli_state *c)
444 {
445         bool ret = True;
446         NTSTATUS status;
447
448         status = cli_tdis(c);
449         if (!NT_STATUS_IS_OK(status)) {
450                 printf("tdis failed (%s)\n", nt_errstr(status));
451                 ret = False;
452         }
453
454         cli_shutdown(c);
455
456         return ret;
457 }
458
459 void torture_conn_set_sockopt(struct cli_state *cli)
460 {
461         smbXcli_conn_set_sockopt(cli->conn, sockops);
462 }
463
464 static NTSTATUS torture_delete_fn(struct file_info *finfo,
465                                   const char *pattern,
466                                   void *state)
467 {
468         NTSTATUS status;
469         char *filename = NULL;
470         char *dirname = NULL;
471         char *p = NULL;
472         TALLOC_CTX *frame = talloc_stackframe();
473         struct cli_state *cli = (struct cli_state *)state;
474
475         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
476                 TALLOC_FREE(frame);
477                 return NT_STATUS_OK;
478         }
479
480         dirname = talloc_strdup(frame, pattern);
481         if (dirname == NULL) {
482                 TALLOC_FREE(frame);
483                 return NT_STATUS_NO_MEMORY;
484         }
485         p = strrchr_m(dirname, '\\');
486         if (p != NULL) {
487                 /* Remove the terminating '\' */
488                 *p = '\0';
489         }
490         if (dirname[0] != '\0') {
491                 filename = talloc_asprintf(frame,
492                                            "%s\\%s",
493                                            dirname,
494                                            finfo->name);
495         } else {
496                 filename = talloc_asprintf(frame,
497                                            "%s",
498                                            finfo->name);
499         }
500         if (filename == NULL) {
501                 TALLOC_FREE(frame);
502                 return NT_STATUS_NO_MEMORY;
503         }
504         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
505                 char *subdirname = talloc_asprintf(frame,
506                                                    "%s\\*",
507                                                    filename);
508                 if (subdirname == NULL) {
509                         TALLOC_FREE(frame);
510                         return NT_STATUS_NO_MEMORY;
511                 }
512                 status = cli_list(cli,
513                                   subdirname,
514                                   FILE_ATTRIBUTE_DIRECTORY |
515                                           FILE_ATTRIBUTE_HIDDEN |
516                                           FILE_ATTRIBUTE_SYSTEM,
517                                   torture_delete_fn,
518                                   cli);
519                 if (!NT_STATUS_IS_OK(status)) {
520                         printf("torture_delete_fn: cli_list "
521                                 "of %s failed (%s)\n",
522                                 subdirname,
523                                 nt_errstr(status));
524                         TALLOC_FREE(frame);
525                         return status;
526                 }
527                 status = cli_rmdir(cli, filename);
528         } else {
529                 status = cli_unlink(cli,
530                                     filename,
531                                     FILE_ATTRIBUTE_SYSTEM |
532                                         FILE_ATTRIBUTE_HIDDEN);
533         }
534         if (!NT_STATUS_IS_OK(status)) {
535                 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
536                         printf("torture_delete_fn: cli_rmdir"
537                                 " of %s failed (%s)\n",
538                                 filename,
539                                 nt_errstr(status));
540                 } else {
541                         printf("torture_delete_fn: cli_unlink"
542                                 " of %s failed (%s)\n",
543                                 filename,
544                                 nt_errstr(status));
545                 }
546         }
547         TALLOC_FREE(frame);
548         return status;
549 }
550
551 void torture_deltree(struct cli_state *cli, const char *dname)
552 {
553         char *mask = NULL;
554         NTSTATUS status;
555
556         /* It might be a file */
557         (void)cli_unlink(cli,
558                          dname,
559                          FILE_ATTRIBUTE_SYSTEM |
560                                 FILE_ATTRIBUTE_HIDDEN);
561
562         mask = talloc_asprintf(cli,
563                                "%s\\*",
564                                dname);
565         if (mask == NULL) {
566                 printf("torture_deltree: talloc_asprintf failed\n");
567                 return;
568         }
569
570         status = cli_list(cli,
571                         mask,
572                         FILE_ATTRIBUTE_DIRECTORY |
573                                 FILE_ATTRIBUTE_HIDDEN|
574                                 FILE_ATTRIBUTE_SYSTEM,
575                         torture_delete_fn,
576                         cli);
577         if (!NT_STATUS_IS_OK(status)) {
578                 printf("torture_deltree: cli_list of %s failed (%s)\n",
579                         mask,
580                         nt_errstr(status));
581         }
582         TALLOC_FREE(mask);
583         status = cli_rmdir(cli, dname);
584         if (!NT_STATUS_IS_OK(status)) {
585                 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
586                         dname,
587                         nt_errstr(status));
588         }
589 }
590
591 /* check if the server produced the expected dos or nt error code */
592 static bool check_both_error(int line, NTSTATUS status,
593                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
594 {
595         if (NT_STATUS_IS_DOS(status)) {
596                 uint8_t cclass;
597                 uint32_t num;
598
599                 /* Check DOS error */
600                 cclass = NT_STATUS_DOS_CLASS(status);
601                 num = NT_STATUS_DOS_CODE(status);
602
603                 if (eclass != cclass || ecode != num) {
604                         printf("unexpected error code class=%d code=%d\n",
605                                (int)cclass, (int)num);
606                         printf(" expected %d/%d %s (line=%d)\n",
607                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
608                         return false;
609                 }
610         } else {
611                 /* Check NT error */
612                 if (!NT_STATUS_EQUAL(nterr, status)) {
613                         printf("unexpected error code %s\n",
614                                 nt_errstr(status));
615                         printf(" expected %s (line=%d)\n",
616                                 nt_errstr(nterr), line);
617                         return false;
618                 }
619         }
620
621         return true;
622 }
623
624
625 /* check if the server produced the expected error code */
626 static bool check_error(int line, NTSTATUS status,
627                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
628 {
629         if (NT_STATUS_IS_DOS(status)) {
630                 uint8_t cclass;
631                 uint32_t num;
632
633                 /* Check DOS error */
634
635                 cclass = NT_STATUS_DOS_CLASS(status);
636                 num = NT_STATUS_DOS_CODE(status);
637
638                 if (eclass != cclass || ecode != num) {
639                         printf("unexpected error code class=%d code=%d\n",
640                                (int)cclass, (int)num);
641                         printf(" expected %d/%d %s (line=%d)\n",
642                                (int)eclass, (int)ecode, nt_errstr(nterr),
643                                line);
644                         return False;
645                 }
646
647         } else {
648                 /* Check NT error */
649
650                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
651                         printf("unexpected error code %s\n",
652                                nt_errstr(status));
653                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
654                                line);
655                         return False;
656                 }
657         }
658
659         return True;
660 }
661
662 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
663                         const char *fname,
664                         time_t *change_time,
665                         time_t *access_time,
666                         time_t *write_time,
667                         off_t *size,
668                         uint32_t *pattr)
669 {
670         int timezone = smb1cli_conn_server_time_zone(cli->conn);
671         time_t (*date_fn)(const void *buf, int serverzone) = NULL;
672         uint8_t *rdata = NULL;
673         uint32_t num_rdata;
674         NTSTATUS status;
675
676         status = cli_qpathinfo(talloc_tos(),
677                                cli,
678                                fname,
679                                SMB_INFO_STANDARD,
680                                22,
681                                CLI_BUFFER_SIZE,
682                                &rdata,
683                                &num_rdata);
684         if (!NT_STATUS_IS_OK(status)) {
685                 return status;
686         }
687         if (cli->win95) {
688                 date_fn = make_unix_date;
689         } else {
690                 date_fn = make_unix_date2;
691         }
692
693         if (change_time) {
694                 *change_time = date_fn(rdata + 0, timezone);
695         }
696         if (access_time) {
697                 *access_time = date_fn(rdata + 4, timezone);
698         }
699         if (write_time) {
700                 *write_time = date_fn(rdata + 8, timezone);
701         }
702         if (size) {
703                 *size = PULL_LE_U32(rdata, 12);
704         }
705         if (pattr) {
706                 *pattr = PULL_LE_U16(rdata, l1_attrFile);
707         }
708         return NT_STATUS_OK;
709 }
710
711 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
712 {
713         NTSTATUS status;
714
715         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
716
717         while (!NT_STATUS_IS_OK(status)) {
718                 if (!check_both_error(__LINE__, status, ERRDOS,
719                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
720                         return false;
721                 }
722
723                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
724         }
725
726         return true;
727 }
728
729
730 static bool rw_torture(struct cli_state *c)
731 {
732         const char *lockfname = "\\torture.lck";
733         fstring fname;
734         uint16_t fnum;
735         uint16_t fnum2;
736         pid_t pid2, pid = getpid();
737         int i, j;
738         char buf[1024];
739         bool correct = True;
740         size_t nread = 0;
741         NTSTATUS status;
742
743         memset(buf, '\0', sizeof(buf));
744
745         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
746                          DENY_NONE, &fnum2);
747         if (!NT_STATUS_IS_OK(status)) {
748                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
749         }
750         if (!NT_STATUS_IS_OK(status)) {
751                 printf("open of %s failed (%s)\n",
752                        lockfname, nt_errstr(status));
753                 return False;
754         }
755
756         for (i=0;i<torture_numops;i++) {
757                 unsigned n = (unsigned)sys_random()%10;
758
759                 if (i % 10 == 0) {
760                         printf("%d\r", i); fflush(stdout);
761                 }
762                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
763
764                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
765                         return False;
766                 }
767
768                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
769                                   DENY_ALL, &fnum);
770                 if (!NT_STATUS_IS_OK(status)) {
771                         printf("open failed (%s)\n", nt_errstr(status));
772                         correct = False;
773                         break;
774                 }
775
776                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
777                                       sizeof(pid), NULL);
778                 if (!NT_STATUS_IS_OK(status)) {
779                         printf("write failed (%s)\n", nt_errstr(status));
780                         correct = False;
781                 }
782
783                 for (j=0;j<50;j++) {
784                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
785                                               sizeof(pid)+(j*sizeof(buf)),
786                                               sizeof(buf), NULL);
787                         if (!NT_STATUS_IS_OK(status)) {
788                                 printf("write failed (%s)\n",
789                                        nt_errstr(status));
790                                 correct = False;
791                         }
792                 }
793
794                 pid2 = 0;
795
796                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
797                                   &nread);
798                 if (!NT_STATUS_IS_OK(status)) {
799                         printf("read failed (%s)\n", nt_errstr(status));
800                         correct = false;
801                 } else if (nread != sizeof(pid)) {
802                         printf("read/write compare failed: "
803                                "recv %ld req %ld\n", (unsigned long)nread,
804                                (unsigned long)sizeof(pid));
805                         correct = false;
806                 }
807
808                 if (pid2 != pid) {
809                         printf("data corruption!\n");
810                         correct = False;
811                 }
812
813                 status = cli_close(c, fnum);
814                 if (!NT_STATUS_IS_OK(status)) {
815                         printf("close failed (%s)\n", nt_errstr(status));
816                         correct = False;
817                 }
818
819                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
820                 if (!NT_STATUS_IS_OK(status)) {
821                         printf("unlink failed (%s)\n", nt_errstr(status));
822                         correct = False;
823                 }
824
825                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
826                 if (!NT_STATUS_IS_OK(status)) {
827                         printf("unlock failed (%s)\n", nt_errstr(status));
828                         correct = False;
829                 }
830         }
831
832         cli_close(c, fnum2);
833         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
834
835         printf("%d\n", i);
836
837         return correct;
838 }
839
840 static bool run_torture(int dummy)
841 {
842         struct cli_state *cli;
843         bool ret;
844
845         cli = current_cli;
846
847         smbXcli_conn_set_sockopt(cli->conn, sockops);
848
849         ret = rw_torture(cli);
850
851         if (!torture_close_connection(cli)) {
852                 ret = False;
853         }
854
855         return ret;
856 }
857
858 static bool rw_torture3(struct cli_state *c, char *lockfname)
859 {
860         uint16_t fnum = (uint16_t)-1;
861         unsigned int i = 0;
862         char buf[131072];
863         char buf_rd[131072];
864         unsigned count;
865         unsigned countprev = 0;
866         size_t sent = 0;
867         bool correct = True;
868         NTSTATUS status = NT_STATUS_OK;
869
870         srandom(1);
871         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
872         {
873                 SIVAL(buf, i, sys_random());
874         }
875
876         if (procnum == 0)
877         {
878                 status = cli_unlink(
879                         c, lockfname,
880                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
881                 if (!NT_STATUS_IS_OK(status)) {
882                         printf("unlink failed (%s) (normal, this file should "
883                                "not exist)\n", nt_errstr(status));
884                 }
885
886                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
887                                   DENY_NONE, &fnum);
888                 if (!NT_STATUS_IS_OK(status)) {
889                         printf("first open read/write of %s failed (%s)\n",
890                                         lockfname, nt_errstr(status));
891                         return False;
892                 }
893         }
894         else
895         {
896                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
897                 {
898                         status = cli_openx(c, lockfname, O_RDONLY,
899                                          DENY_NONE, &fnum);
900                         if (NT_STATUS_IS_OK(status)) {
901                                 break;
902                         }
903                         smb_msleep(10);
904                 }
905                 if (!NT_STATUS_IS_OK(status)) {
906                         printf("second open read-only of %s failed (%s)\n",
907                                         lockfname, nt_errstr(status));
908                         return False;
909                 }
910         }
911
912         i = 0;
913         for (count = 0; count < sizeof(buf); count += sent)
914         {
915                 if (count >= countprev) {
916                         printf("%d %8d\r", i, count);
917                         fflush(stdout);
918                         i++;
919                         countprev += (sizeof(buf) / 20);
920                 }
921
922                 if (procnum == 0)
923                 {
924                         sent = ((unsigned)sys_random()%(20))+ 1;
925                         if (sent > sizeof(buf) - count)
926                         {
927                                 sent = sizeof(buf) - count;
928                         }
929
930                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
931                                               count, sent, NULL);
932                         if (!NT_STATUS_IS_OK(status)) {
933                                 printf("write failed (%s)\n",
934                                        nt_errstr(status));
935                                 correct = False;
936                         }
937                 }
938                 else
939                 {
940                         status = cli_read(c, fnum, buf_rd+count, count,
941                                           sizeof(buf)-count, &sent);
942                         if(!NT_STATUS_IS_OK(status)) {
943                                 printf("read failed offset:%d size:%ld (%s)\n",
944                                        count, (unsigned long)sizeof(buf)-count,
945                                        nt_errstr(status));
946                                 correct = False;
947                                 sent = 0;
948                         } else if (sent > 0) {
949                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
950                                 {
951                                         printf("read/write compare failed\n");
952                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
953                                         correct = False;
954                                         break;
955                                 }
956                         }
957                 }
958
959         }
960
961         status = cli_close(c, fnum);
962         if (!NT_STATUS_IS_OK(status)) {
963                 printf("close failed (%s)\n", nt_errstr(status));
964                 correct = False;
965         }
966
967         return correct;
968 }
969
970 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
971 {
972         const char *lockfname = "\\torture2.lck";
973         uint16_t fnum1;
974         uint16_t fnum2;
975         int i;
976         char buf[131072];
977         char buf_rd[131072];
978         bool correct = True;
979         size_t bytes_read;
980         NTSTATUS status;
981
982         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
983         if (!NT_STATUS_IS_OK(status)) {
984                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
985         }
986
987         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
988                           DENY_NONE, &fnum1);
989         if (!NT_STATUS_IS_OK(status)) {
990                 printf("first open read/write of %s failed (%s)\n",
991                                 lockfname, nt_errstr(status));
992                 return False;
993         }
994
995         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
996         if (!NT_STATUS_IS_OK(status)) {
997                 printf("second open read-only of %s failed (%s)\n",
998                                 lockfname, nt_errstr(status));
999                 cli_close(c1, fnum1);
1000                 return False;
1001         }
1002
1003         for (i = 0; i < torture_numops; i++)
1004         {
1005                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1006                 if (i % 10 == 0) {
1007                         printf("%d\r", i); fflush(stdout);
1008                 }
1009
1010                 generate_random_buffer((unsigned char *)buf, buf_size);
1011
1012                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1013                                       buf_size, NULL);
1014                 if (!NT_STATUS_IS_OK(status)) {
1015                         printf("write failed (%s)\n", nt_errstr(status));
1016                         correct = False;
1017                         break;
1018                 }
1019
1020                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1021                 if(!NT_STATUS_IS_OK(status)) {
1022                         printf("read failed (%s)\n", nt_errstr(status));
1023                         correct = false;
1024                         break;
1025                 } else if (bytes_read != buf_size) {
1026                         printf("read failed\n");
1027                         printf("read %ld, expected %ld\n",
1028                                (unsigned long)bytes_read,
1029                                (unsigned long)buf_size);
1030                         correct = False;
1031                         break;
1032                 }
1033
1034                 if (memcmp(buf_rd, buf, buf_size) != 0)
1035                 {
1036                         printf("read/write compare failed\n");
1037                         correct = False;
1038                         break;
1039                 }
1040         }
1041
1042         status = cli_close(c2, fnum2);
1043         if (!NT_STATUS_IS_OK(status)) {
1044                 printf("close failed (%s)\n", nt_errstr(status));
1045                 correct = False;
1046         }
1047
1048         status = cli_close(c1, fnum1);
1049         if (!NT_STATUS_IS_OK(status)) {
1050                 printf("close failed (%s)\n", nt_errstr(status));
1051                 correct = False;
1052         }
1053
1054         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1055         if (!NT_STATUS_IS_OK(status)) {
1056                 printf("unlink failed (%s)\n", nt_errstr(status));
1057                 correct = False;
1058         }
1059
1060         return correct;
1061 }
1062
1063 static bool run_readwritetest(int dummy)
1064 {
1065         struct cli_state *cli1, *cli2;
1066         bool test1, test2 = False;
1067
1068         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1069                 return False;
1070         }
1071         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1072         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1073
1074         printf("starting readwritetest\n");
1075
1076         test1 = rw_torture2(cli1, cli2);
1077         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1078
1079         if (test1) {
1080                 test2 = rw_torture2(cli1, cli1);
1081                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1082         }
1083
1084         if (!torture_close_connection(cli1)) {
1085                 test1 = False;
1086         }
1087
1088         if (!torture_close_connection(cli2)) {
1089                 test2 = False;
1090         }
1091
1092         return (test1 && test2);
1093 }
1094
1095 static bool run_readwritemulti(int dummy)
1096 {
1097         struct cli_state *cli;
1098         bool test;
1099
1100         cli = current_cli;
1101
1102         smbXcli_conn_set_sockopt(cli->conn, sockops);
1103
1104         printf("run_readwritemulti: fname %s\n", randomfname);
1105         test = rw_torture3(cli, randomfname);
1106
1107         if (!torture_close_connection(cli)) {
1108                 test = False;
1109         }
1110
1111         return test;
1112 }
1113
1114 static bool run_readwritelarge_internal(void)
1115 {
1116         static struct cli_state *cli1;
1117         uint16_t fnum1;
1118         const char *lockfname = "\\large.dat";
1119         off_t fsize;
1120         char buf[126*1024];
1121         bool correct = True;
1122         NTSTATUS status;
1123
1124         if (!torture_open_connection(&cli1, 0)) {
1125                 return False;
1126         }
1127         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1128         memset(buf,'\0',sizeof(buf));
1129
1130         printf("starting readwritelarge_internal\n");
1131
1132         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1133
1134         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1135                           DENY_NONE, &fnum1);
1136         if (!NT_STATUS_IS_OK(status)) {
1137                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1138                 return False;
1139         }
1140
1141         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1142
1143         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1144                                      NULL, NULL, NULL);
1145         if (!NT_STATUS_IS_OK(status)) {
1146                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1147                 correct = False;
1148         }
1149
1150         if (fsize == sizeof(buf))
1151                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1152                        (unsigned long)fsize);
1153         else {
1154                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1155                        (unsigned long)fsize);
1156                 correct = False;
1157         }
1158
1159         status = cli_close(cli1, fnum1);
1160         if (!NT_STATUS_IS_OK(status)) {
1161                 printf("close failed (%s)\n", nt_errstr(status));
1162                 correct = False;
1163         }
1164
1165         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1166         if (!NT_STATUS_IS_OK(status)) {
1167                 printf("unlink failed (%s)\n", nt_errstr(status));
1168                 correct = False;
1169         }
1170
1171         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1172                           DENY_NONE, &fnum1);
1173         if (!NT_STATUS_IS_OK(status)) {
1174                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1175                 return False;
1176         }
1177
1178         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1179
1180         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1181                                      NULL, NULL, NULL);
1182         if (!NT_STATUS_IS_OK(status)) {
1183                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1184                 correct = False;
1185         }
1186
1187         if (fsize == sizeof(buf))
1188                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1189                        (unsigned long)fsize);
1190         else {
1191                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1192                        (unsigned long)fsize);
1193                 correct = False;
1194         }
1195
1196         status = cli_close(cli1, fnum1);
1197         if (!NT_STATUS_IS_OK(status)) {
1198                 printf("close failed (%s)\n", nt_errstr(status));
1199                 correct = False;
1200         }
1201
1202         if (!torture_close_connection(cli1)) {
1203                 correct = False;
1204         }
1205         return correct;
1206 }
1207
1208 static bool run_readwritelarge(int dummy)
1209 {
1210         return run_readwritelarge_internal();
1211 }
1212
1213 static bool run_readwritelarge_signtest(int dummy)
1214 {
1215         bool ret;
1216         signing_state = SMB_SIGNING_REQUIRED;
1217         ret = run_readwritelarge_internal();
1218         signing_state = SMB_SIGNING_DEFAULT;
1219         return ret;
1220 }
1221
1222 int line_count = 0;
1223 int nbio_id;
1224
1225 #define ival(s) strtol(s, NULL, 0)
1226
1227 /* run a test that simulates an approximate netbench client load */
1228 static bool run_netbench(int client)
1229 {
1230         struct cli_state *cli;
1231         int i;
1232         char line[1024];
1233         char cname[20];
1234         FILE *f;
1235         const char *params[20];
1236         bool correct = True;
1237
1238         cli = current_cli;
1239
1240         nbio_id = client;
1241
1242         smbXcli_conn_set_sockopt(cli->conn, sockops);
1243
1244         nb_setup(cli);
1245
1246         slprintf(cname,sizeof(cname)-1, "client%d", client);
1247
1248         f = fopen(client_txt, "r");
1249
1250         if (!f) {
1251                 perror(client_txt);
1252                 return False;
1253         }
1254
1255         while (fgets(line, sizeof(line)-1, f)) {
1256                 char *saveptr;
1257                 line_count++;
1258
1259                 line[strlen(line)-1] = 0;
1260
1261                 /* printf("[%d] %s\n", line_count, line); */
1262
1263                 all_string_sub(line,"client1", cname, sizeof(line));
1264
1265                 /* parse the command parameters */
1266                 params[0] = strtok_r(line, " ", &saveptr);
1267                 i = 0;
1268                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1269
1270                 params[i] = "";
1271
1272                 if (i < 2) continue;
1273
1274                 if (!strncmp(params[0],"SMB", 3)) {
1275                         printf("ERROR: You are using a dbench 1 load file\n");
1276                         exit(1);
1277                 }
1278
1279                 if (!strcmp(params[0],"NTCreateX")) {
1280                         nb_createx(params[1], ival(params[2]), ival(params[3]),
1281                                    ival(params[4]));
1282                 } else if (!strcmp(params[0],"Close")) {
1283                         nb_close(ival(params[1]));
1284                 } else if (!strcmp(params[0],"Rename")) {
1285                         nb_rename(params[1], params[2]);
1286                 } else if (!strcmp(params[0],"Unlink")) {
1287                         nb_unlink(params[1]);
1288                 } else if (!strcmp(params[0],"Deltree")) {
1289                         nb_deltree(params[1]);
1290                 } else if (!strcmp(params[0],"Rmdir")) {
1291                         nb_rmdir(params[1]);
1292                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1293                         nb_qpathinfo(params[1]);
1294                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1295                         nb_qfileinfo(ival(params[1]));
1296                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1297                         nb_qfsinfo(ival(params[1]));
1298                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1299                         nb_findfirst(params[1]);
1300                 } else if (!strcmp(params[0],"WriteX")) {
1301                         nb_writex(ival(params[1]),
1302                                   ival(params[2]), ival(params[3]), ival(params[4]));
1303                 } else if (!strcmp(params[0],"ReadX")) {
1304                         nb_readx(ival(params[1]),
1305                                   ival(params[2]), ival(params[3]), ival(params[4]));
1306                 } else if (!strcmp(params[0],"Flush")) {
1307                         nb_flush(ival(params[1]));
1308                 } else {
1309                         printf("Unknown operation %s\n", params[0]);
1310                         exit(1);
1311                 }
1312         }
1313         fclose(f);
1314
1315         nb_cleanup();
1316
1317         if (!torture_close_connection(cli)) {
1318                 correct = False;
1319         }
1320
1321         return correct;
1322 }
1323
1324
1325 /* run a test that simulates an approximate netbench client load */
1326 static bool run_nbench(int dummy)
1327 {
1328         double t;
1329         bool correct = True;
1330
1331         nbio_shmem(torture_nprocs);
1332
1333         nbio_id = -1;
1334
1335         signal(SIGALRM, nb_alarm);
1336         alarm(1);
1337         t = create_procs(run_netbench, &correct);
1338         alarm(0);
1339
1340         printf("\nThroughput %g MB/sec\n",
1341                1.0e-6 * nbio_total() / t);
1342         return correct;
1343 }
1344
1345
1346 /*
1347   This test checks for two things:
1348
1349   1) correct support for retaining locks over a close (ie. the server
1350      must not use posix semantics)
1351   2) support for lock timeouts
1352  */
1353 static bool run_locktest1(int dummy)
1354 {
1355         struct cli_state *cli1, *cli2;
1356         const char *fname = "\\lockt1.lck";
1357         uint16_t fnum1, fnum2, fnum3;
1358         time_t t1, t2;
1359         unsigned lock_timeout;
1360         NTSTATUS status;
1361
1362         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1363                 return False;
1364         }
1365         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1366         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1367
1368         printf("starting locktest1\n");
1369
1370         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1371
1372         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1373                           &fnum1);
1374         if (!NT_STATUS_IS_OK(status)) {
1375                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1376                 return False;
1377         }
1378
1379         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1380         if (!NT_STATUS_IS_OK(status)) {
1381                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1382                 return False;
1383         }
1384
1385         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1386         if (!NT_STATUS_IS_OK(status)) {
1387                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1388                 return False;
1389         }
1390
1391         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1392         if (!NT_STATUS_IS_OK(status)) {
1393                 printf("lock1 failed (%s)\n", nt_errstr(status));
1394                 return false;
1395         }
1396
1397         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1398         if (NT_STATUS_IS_OK(status)) {
1399                 printf("lock2 succeeded! This is a locking bug\n");
1400                 return false;
1401         } else {
1402                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1403                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1404                         return false;
1405                 }
1406         }
1407
1408         lock_timeout = (1 + (random() % 20));
1409         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1410         t1 = time(NULL);
1411         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1412         if (NT_STATUS_IS_OK(status)) {
1413                 printf("lock3 succeeded! This is a locking bug\n");
1414                 return false;
1415         } else {
1416                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1417                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1418                         return false;
1419                 }
1420         }
1421         t2 = time(NULL);
1422
1423         if (ABS(t2 - t1) < lock_timeout-1) {
1424                 printf("error: This server appears not to support timed lock requests\n");
1425         }
1426
1427         printf("server slept for %u seconds for a %u second timeout\n",
1428                (unsigned int)(t2-t1), lock_timeout);
1429
1430         status = cli_close(cli1, fnum2);
1431         if (!NT_STATUS_IS_OK(status)) {
1432                 printf("close1 failed (%s)\n", nt_errstr(status));
1433                 return False;
1434         }
1435
1436         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1437         if (NT_STATUS_IS_OK(status)) {
1438                 printf("lock4 succeeded! This is a locking bug\n");
1439                 return false;
1440         } else {
1441                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1442                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1443                         return false;
1444                 }
1445         }
1446
1447         status = cli_close(cli1, fnum1);
1448         if (!NT_STATUS_IS_OK(status)) {
1449                 printf("close2 failed (%s)\n", nt_errstr(status));
1450                 return False;
1451         }
1452
1453         status = cli_close(cli2, fnum3);
1454         if (!NT_STATUS_IS_OK(status)) {
1455                 printf("close3 failed (%s)\n", nt_errstr(status));
1456                 return False;
1457         }
1458
1459         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1460         if (!NT_STATUS_IS_OK(status)) {
1461                 printf("unlink failed (%s)\n", nt_errstr(status));
1462                 return False;
1463         }
1464
1465
1466         if (!torture_close_connection(cli1)) {
1467                 return False;
1468         }
1469
1470         if (!torture_close_connection(cli2)) {
1471                 return False;
1472         }
1473
1474         printf("Passed locktest1\n");
1475         return True;
1476 }
1477
1478 /*
1479   this checks to see if a secondary tconx can use open files from an
1480   earlier tconx
1481  */
1482 static bool run_tcon_test(int dummy)
1483 {
1484         static struct cli_state *cli;
1485         const char *fname = "\\tcontest.tmp";
1486         uint16_t fnum1;
1487         uint32_t cnum1, cnum2, cnum3;
1488         struct smbXcli_tcon *orig_tcon = NULL;
1489         char *orig_share = NULL;
1490         uint16_t vuid1, vuid2;
1491         char buf[4];
1492         bool ret = True;
1493         NTSTATUS status;
1494
1495         memset(buf, '\0', sizeof(buf));
1496
1497         if (!torture_open_connection(&cli, 0)) {
1498                 return False;
1499         }
1500         smbXcli_conn_set_sockopt(cli->conn, sockops);
1501
1502         printf("starting tcontest\n");
1503
1504         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1505
1506         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1507         if (!NT_STATUS_IS_OK(status)) {
1508                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1509                 return False;
1510         }
1511
1512         cnum1 = cli_state_get_tid(cli);
1513         vuid1 = cli_state_get_uid(cli);
1514
1515         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1516         if (!NT_STATUS_IS_OK(status)) {
1517                 printf("initial write failed (%s)", nt_errstr(status));
1518                 return False;
1519         }
1520
1521         cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1522
1523         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1524         if (!NT_STATUS_IS_OK(status)) {
1525                 printf("%s refused 2nd tree connect (%s)\n", host,
1526                        nt_errstr(status));
1527                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1528                 cli_shutdown(cli);
1529                 return False;
1530         }
1531
1532         cnum2 = cli_state_get_tid(cli);
1533         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1534         vuid2 = cli_state_get_uid(cli) + 1;
1535
1536         /* try a write with the wrong tid */
1537         cli_state_set_tid(cli, cnum2);
1538
1539         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1540         if (NT_STATUS_IS_OK(status)) {
1541                 printf("* server allows write with wrong TID\n");
1542                 ret = False;
1543         } else {
1544                 printf("server fails write with wrong TID : %s\n",
1545                        nt_errstr(status));
1546         }
1547
1548
1549         /* try a write with an invalid tid */
1550         cli_state_set_tid(cli, cnum3);
1551
1552         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1553         if (NT_STATUS_IS_OK(status)) {
1554                 printf("* server allows write with invalid TID\n");
1555                 ret = False;
1556         } else {
1557                 printf("server fails write with invalid TID : %s\n",
1558                        nt_errstr(status));
1559         }
1560
1561         /* try a write with an invalid vuid */
1562         cli_state_set_uid(cli, vuid2);
1563         cli_state_set_tid(cli, cnum1);
1564
1565         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1566         if (NT_STATUS_IS_OK(status)) {
1567                 printf("* server allows write with invalid VUID\n");
1568                 ret = False;
1569         } else {
1570                 printf("server fails write with invalid VUID : %s\n",
1571                        nt_errstr(status));
1572         }
1573
1574         cli_state_set_tid(cli, cnum1);
1575         cli_state_set_uid(cli, vuid1);
1576
1577         status = cli_close(cli, fnum1);
1578         if (!NT_STATUS_IS_OK(status)) {
1579                 printf("close failed (%s)\n", nt_errstr(status));
1580                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1581                 cli_shutdown(cli);
1582                 return False;
1583         }
1584
1585         cli_state_set_tid(cli, cnum2);
1586
1587         status = cli_tdis(cli);
1588         if (!NT_STATUS_IS_OK(status)) {
1589                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1590                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1591                 cli_shutdown(cli);
1592                 return False;
1593         }
1594
1595         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1596
1597         cli_state_set_tid(cli, cnum1);
1598
1599         if (!torture_close_connection(cli)) {
1600                 return False;
1601         }
1602
1603         return ret;
1604 }
1605
1606
1607 /*
1608  checks for old style tcon support
1609  */
1610 static bool run_tcon2_test(int dummy)
1611 {
1612         static struct cli_state *cli;
1613         uint16_t cnum, max_xmit;
1614         char *service;
1615         NTSTATUS status;
1616
1617         if (!torture_open_connection(&cli, 0)) {
1618                 return False;
1619         }
1620         smbXcli_conn_set_sockopt(cli->conn, sockops);
1621
1622         printf("starting tcon2 test\n");
1623
1624         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1625                 return false;
1626         }
1627
1628         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1629
1630         SAFE_FREE(service);
1631
1632         if (!NT_STATUS_IS_OK(status)) {
1633                 printf("tcon2 failed : %s\n", nt_errstr(status));
1634         } else {
1635                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1636                        (int)max_xmit, (int)cnum);
1637         }
1638
1639         if (!torture_close_connection(cli)) {
1640                 return False;
1641         }
1642
1643         printf("Passed tcon2 test\n");
1644         return True;
1645 }
1646
1647 static bool tcon_devtest(struct cli_state *cli,
1648                          const char *myshare, const char *devtype,
1649                          const char *return_devtype,
1650                          NTSTATUS expected_error)
1651 {
1652         NTSTATUS status;
1653         bool ret;
1654
1655         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1656
1657         if (NT_STATUS_IS_OK(expected_error)) {
1658                 if (NT_STATUS_IS_OK(status)) {
1659                         if (return_devtype != NULL &&
1660                             strequal(cli->dev, return_devtype)) {
1661                                 ret = True;
1662                         } else {
1663                                 printf("tconX to share %s with type %s "
1664                                        "succeeded but returned the wrong "
1665                                        "device type (got [%s] but should have got [%s])\n",
1666                                        myshare, devtype, cli->dev, return_devtype);
1667                                 ret = False;
1668                         }
1669                 } else {
1670                         printf("tconX to share %s with type %s "
1671                                "should have succeeded but failed\n",
1672                                myshare, devtype);
1673                         ret = False;
1674                 }
1675                 cli_tdis(cli);
1676         } else {
1677                 if (NT_STATUS_IS_OK(status)) {
1678                         printf("tconx to share %s with type %s "
1679                                "should have failed but succeeded\n",
1680                                myshare, devtype);
1681                         ret = False;
1682                 } else {
1683                         if (NT_STATUS_EQUAL(status, expected_error)) {
1684                                 ret = True;
1685                         } else {
1686                                 printf("Returned unexpected error\n");
1687                                 ret = False;
1688                         }
1689                 }
1690         }
1691         return ret;
1692 }
1693
1694 /*
1695  checks for correct tconX support
1696  */
1697 static bool run_tcon_devtype_test(int dummy)
1698 {
1699         static struct cli_state *cli1 = NULL;
1700         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1701         NTSTATUS status;
1702         bool ret = True;
1703
1704         status = cli_full_connection_creds(&cli1,
1705                                            myname,
1706                                            host,
1707                                            NULL, /* dest_ss */
1708                                            port_to_use,
1709                                            NULL, /* service */
1710                                            NULL, /* service_type */
1711                                            torture_creds,
1712                                            flags);
1713
1714         if (!NT_STATUS_IS_OK(status)) {
1715                 printf("could not open connection\n");
1716                 return False;
1717         }
1718
1719         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1720                 ret = False;
1721
1722         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1723                 ret = False;
1724
1725         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1726                 ret = False;
1727
1728         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1729                 ret = False;
1730
1731         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1732                 ret = False;
1733
1734         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1735                 ret = False;
1736
1737         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1738                 ret = False;
1739
1740         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741                 ret = False;
1742
1743         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1744                 ret = False;
1745
1746         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1747                 ret = False;
1748
1749         cli_shutdown(cli1);
1750
1751         if (ret)
1752                 printf("Passed tcondevtest\n");
1753
1754         return ret;
1755 }
1756
1757
1758 /*
1759   This test checks that
1760
1761   1) the server supports multiple locking contexts on the one SMB
1762   connection, distinguished by PID.
1763
1764   2) the server correctly fails overlapping locks made by the same PID (this
1765      goes against POSIX behaviour, which is why it is tricky to implement)
1766
1767   3) the server denies unlock requests by an incorrect client PID
1768 */
1769 static bool run_locktest2(int dummy)
1770 {
1771         static struct cli_state *cli;
1772         const char *fname = "\\lockt2.lck";
1773         uint16_t fnum1, fnum2, fnum3;
1774         bool correct = True;
1775         NTSTATUS status;
1776
1777         if (!torture_open_connection(&cli, 0)) {
1778                 return False;
1779         }
1780
1781         smbXcli_conn_set_sockopt(cli->conn, sockops);
1782
1783         printf("starting locktest2\n");
1784
1785         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1786
1787         cli_setpid(cli, 1);
1788
1789         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1790         if (!NT_STATUS_IS_OK(status)) {
1791                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1792                 return False;
1793         }
1794
1795         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1796         if (!NT_STATUS_IS_OK(status)) {
1797                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1798                 return False;
1799         }
1800
1801         cli_setpid(cli, 2);
1802
1803         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1804         if (!NT_STATUS_IS_OK(status)) {
1805                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1806                 return False;
1807         }
1808
1809         cli_setpid(cli, 1);
1810
1811         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1812         if (!NT_STATUS_IS_OK(status)) {
1813                 printf("lock1 failed (%s)\n", nt_errstr(status));
1814                 return false;
1815         }
1816
1817         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1818         if (NT_STATUS_IS_OK(status)) {
1819                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1820                 correct = false;
1821         } else {
1822                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1823                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1824                         return false;
1825                 }
1826         }
1827
1828         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1829         if (NT_STATUS_IS_OK(status)) {
1830                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1831                 correct = false;
1832         } else {
1833                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1834                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1835                         return false;
1836                 }
1837         }
1838
1839         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1840         if (NT_STATUS_IS_OK(status)) {
1841                 printf("READ lock2 succeeded! This is a locking bug\n");
1842                 correct = false;
1843         } else {
1844                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1845                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1846                         return false;
1847                 }
1848         }
1849
1850         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1851         if (!NT_STATUS_IS_OK(status)) {
1852                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1853         }
1854         cli_setpid(cli, 2);
1855         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1856                 printf("unlock at 100 succeeded! This is a locking bug\n");
1857                 correct = False;
1858         }
1859
1860         status = cli_unlock(cli, fnum1, 0, 4);
1861         if (NT_STATUS_IS_OK(status)) {
1862                 printf("unlock1 succeeded! This is a locking bug\n");
1863                 correct = false;
1864         } else {
1865                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1866                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1867                         return false;
1868                 }
1869         }
1870
1871         status = cli_unlock(cli, fnum1, 0, 8);
1872         if (NT_STATUS_IS_OK(status)) {
1873                 printf("unlock2 succeeded! This is a locking bug\n");
1874                 correct = false;
1875         } else {
1876                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1877                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1878                         return false;
1879                 }
1880         }
1881
1882         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1883         if (NT_STATUS_IS_OK(status)) {
1884                 printf("lock3 succeeded! This is a locking bug\n");
1885                 correct = false;
1886         } else {
1887                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1888                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1889                         return false;
1890                 }
1891         }
1892
1893         cli_setpid(cli, 1);
1894
1895         status = cli_close(cli, fnum1);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 printf("close1 failed (%s)\n", nt_errstr(status));
1898                 return False;
1899         }
1900
1901         status = cli_close(cli, fnum2);
1902         if (!NT_STATUS_IS_OK(status)) {
1903                 printf("close2 failed (%s)\n", nt_errstr(status));
1904                 return False;
1905         }
1906
1907         status = cli_close(cli, fnum3);
1908         if (!NT_STATUS_IS_OK(status)) {
1909                 printf("close3 failed (%s)\n", nt_errstr(status));
1910                 return False;
1911         }
1912
1913         if (!torture_close_connection(cli)) {
1914                 correct = False;
1915         }
1916
1917         printf("locktest2 finished\n");
1918
1919         return correct;
1920 }
1921
1922
1923 /*
1924   This test checks that
1925
1926   1) the server supports the full offset range in lock requests
1927 */
1928 static bool run_locktest3(int dummy)
1929 {
1930         static struct cli_state *cli1, *cli2;
1931         const char *fname = "\\lockt3.lck";
1932         uint16_t fnum1, fnum2;
1933         int i;
1934         uint32_t offset;
1935         bool correct = True;
1936         NTSTATUS status;
1937
1938 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1939
1940         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1941                 return False;
1942         }
1943         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1944         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1945
1946         printf("starting locktest3\n");
1947
1948         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1949
1950         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1951                          &fnum1);
1952         if (!NT_STATUS_IS_OK(status)) {
1953                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1954                 return False;
1955         }
1956
1957         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1958         if (!NT_STATUS_IS_OK(status)) {
1959                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1960                 return False;
1961         }
1962
1963         for (offset=i=0;i<torture_numops;i++) {
1964                 NEXT_OFFSET;
1965
1966                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1967                 if (!NT_STATUS_IS_OK(status)) {
1968                         printf("lock1 %d failed (%s)\n",
1969                                i,
1970                                nt_errstr(status));
1971                         return False;
1972                 }
1973
1974                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1975                 if (!NT_STATUS_IS_OK(status)) {
1976                         printf("lock2 %d failed (%s)\n",
1977                                i,
1978                                nt_errstr(status));
1979                         return False;
1980                 }
1981         }
1982
1983         for (offset=i=0;i<torture_numops;i++) {
1984                 NEXT_OFFSET;
1985
1986                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1987                 if (NT_STATUS_IS_OK(status)) {
1988                         printf("error: lock1 %d succeeded!\n", i);
1989                         return False;
1990                 }
1991
1992                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1993                 if (NT_STATUS_IS_OK(status)) {
1994                         printf("error: lock2 %d succeeded!\n", i);
1995                         return False;
1996                 }
1997
1998                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1999                 if (NT_STATUS_IS_OK(status)) {
2000                         printf("error: lock3 %d succeeded!\n", i);
2001                         return False;
2002                 }
2003
2004                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2005                 if (NT_STATUS_IS_OK(status)) {
2006                         printf("error: lock4 %d succeeded!\n", i);
2007                         return False;
2008                 }
2009         }
2010
2011         for (offset=i=0;i<torture_numops;i++) {
2012                 NEXT_OFFSET;
2013
2014                 status = cli_unlock(cli1, fnum1, offset-1, 1);
2015                 if (!NT_STATUS_IS_OK(status)) {
2016                         printf("unlock1 %d failed (%s)\n",
2017                                i,
2018                                nt_errstr(status));
2019                         return False;
2020                 }
2021
2022                 status = cli_unlock(cli2, fnum2, offset-2, 1);
2023                 if (!NT_STATUS_IS_OK(status)) {
2024                         printf("unlock2 %d failed (%s)\n",
2025                                i,
2026                                nt_errstr(status));
2027                         return False;
2028                 }
2029         }
2030
2031         status = cli_close(cli1, fnum1);
2032         if (!NT_STATUS_IS_OK(status)) {
2033                 printf("close1 failed (%s)\n", nt_errstr(status));
2034                 return False;
2035         }
2036
2037         status = cli_close(cli2, fnum2);
2038         if (!NT_STATUS_IS_OK(status)) {
2039                 printf("close2 failed (%s)\n", nt_errstr(status));
2040                 return False;
2041         }
2042
2043         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2044         if (!NT_STATUS_IS_OK(status)) {
2045                 printf("unlink failed (%s)\n", nt_errstr(status));
2046                 return False;
2047         }
2048
2049         if (!torture_close_connection(cli1)) {
2050                 correct = False;
2051         }
2052
2053         if (!torture_close_connection(cli2)) {
2054                 correct = False;
2055         }
2056
2057         printf("finished locktest3\n");
2058
2059         return correct;
2060 }
2061
2062 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2063                            char *buf, off_t offset, size_t size,
2064                            size_t *nread, size_t expect)
2065 {
2066         NTSTATUS status;
2067         size_t l_nread;
2068
2069         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2070
2071         if(!NT_STATUS_IS_OK(status)) {
2072                 return false;
2073         } else if (l_nread != expect) {
2074                 return false;
2075         }
2076
2077         if (nread) {
2078                 *nread = l_nread;
2079         }
2080
2081         return true;
2082 }
2083
2084 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2085         printf("** "); correct = False; \
2086         }
2087
2088 /*
2089   looks at overlapping locks
2090 */
2091 static bool run_locktest4(int dummy)
2092 {
2093         static struct cli_state *cli1, *cli2;
2094         const char *fname = "\\lockt4.lck";
2095         uint16_t fnum1, fnum2, f;
2096         bool ret;
2097         char buf[1000];
2098         bool correct = True;
2099         NTSTATUS status;
2100
2101         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2102                 return False;
2103         }
2104
2105         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2106         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2107
2108         printf("starting locktest4\n");
2109
2110         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2111
2112         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2113         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2114
2115         memset(buf, 0, sizeof(buf));
2116
2117         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2118                               NULL);
2119         if (!NT_STATUS_IS_OK(status)) {
2120                 printf("Failed to create file: %s\n", nt_errstr(status));
2121                 correct = False;
2122                 goto fail;
2123         }
2124
2125         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2126               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2127         EXPECTED(ret, False);
2128         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2129
2130         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2131               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2132         EXPECTED(ret, True);
2133         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2134
2135         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2136               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2137         EXPECTED(ret, False);
2138         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2139
2140         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2141               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2142         EXPECTED(ret, True);
2143         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2144
2145         ret = (cli_setpid(cli1, 1),
2146               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2147               (cli_setpid(cli1, 2),
2148               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2149         EXPECTED(ret, False);
2150         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2151
2152         ret = (cli_setpid(cli1, 1),
2153               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2154               (cli_setpid(cli1, 2),
2155               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2156         EXPECTED(ret, True);
2157         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2158
2159         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2160               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2161         EXPECTED(ret, True);
2162         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2163
2164         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2165               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2166         EXPECTED(ret, False);
2167         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2168
2169         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2170               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2171         EXPECTED(ret, False);
2172         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2173
2174         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2175               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2176         EXPECTED(ret, True);
2177         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2178
2179         ret = (cli_setpid(cli1, 1),
2180              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2181              (cli_setpid(cli1, 2),
2182              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2183         EXPECTED(ret, False);
2184         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2185
2186         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2187               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2188               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2189         EXPECTED(ret, False);
2190         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2191
2192
2193         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2194               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2195         EXPECTED(ret, False);
2196         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2197
2198         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2199         ret = NT_STATUS_IS_OK(status);
2200         if (ret) {
2201                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2202                                       NULL);
2203                 ret = NT_STATUS_IS_OK(status);
2204         }
2205         EXPECTED(ret, False);
2206         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2207
2208
2209         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2210               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2211               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2212               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2213         EXPECTED(ret, True);
2214         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2215
2216
2217         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2218               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2219               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2220               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2221               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2222                                              150, 4, NULL))) &&
2223               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2224         EXPECTED(ret, True);
2225         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2226
2227         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2228               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2229               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2230                                            160, 4, NULL)) &&
2231               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2232         EXPECTED(ret, True);
2233         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2234
2235         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2236               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2237               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2238                                            170, 4, NULL)) &&
2239               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2240         EXPECTED(ret, True);
2241         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2242
2243         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2244               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2245               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2246               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2247                                             190, 4, NULL)) &&
2248               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2249         EXPECTED(ret, True);
2250         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2251
2252         cli_close(cli1, fnum1);
2253         cli_close(cli2, fnum2);
2254         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2255         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2256         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2257               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2258               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2259               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2260               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2261         cli_close(cli1, f);
2262         cli_close(cli1, fnum1);
2263         EXPECTED(ret, True);
2264         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2265
2266  fail:
2267         cli_close(cli1, fnum1);
2268         cli_close(cli2, fnum2);
2269         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2270         torture_close_connection(cli1);
2271         torture_close_connection(cli2);
2272
2273         printf("finished locktest4\n");
2274         return correct;
2275 }
2276
2277 /*
2278   looks at lock upgrade/downgrade.
2279 */
2280 static bool run_locktest5(int dummy)
2281 {
2282         static struct cli_state *cli1, *cli2;
2283         const char *fname = "\\lockt5.lck";
2284         uint16_t fnum1, fnum2, fnum3;
2285         bool ret;
2286         char buf[1000];
2287         bool correct = True;
2288         NTSTATUS status;
2289
2290         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2291                 return False;
2292         }
2293
2294         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2295         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2296
2297         printf("starting locktest5\n");
2298
2299         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2300
2301         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2302         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2303         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2304
2305         memset(buf, 0, sizeof(buf));
2306
2307         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2308                               NULL);
2309         if (!NT_STATUS_IS_OK(status)) {
2310                 printf("Failed to create file: %s\n", nt_errstr(status));
2311                 correct = False;
2312                 goto fail;
2313         }
2314
2315         /* Check for NT bug... */
2316         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2317               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2318         cli_close(cli1, fnum1);
2319         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2320         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2321         ret = NT_STATUS_IS_OK(status);
2322         EXPECTED(ret, True);
2323         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2324         cli_close(cli1, fnum1);
2325         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2326         cli_unlock(cli1, fnum3, 0, 1);
2327
2328         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2329               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2330         EXPECTED(ret, True);
2331         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2332
2333         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2334         ret = NT_STATUS_IS_OK(status);
2335         EXPECTED(ret, False);
2336
2337         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2338
2339         /* Unlock the process 2 lock. */
2340         cli_unlock(cli2, fnum2, 0, 4);
2341
2342         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2343         ret = NT_STATUS_IS_OK(status);
2344         EXPECTED(ret, False);
2345
2346         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2347
2348         /* Unlock the process 1 fnum3 lock. */
2349         cli_unlock(cli1, fnum3, 0, 4);
2350
2351         /* Stack 2 more locks here. */
2352         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2353               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2354
2355         EXPECTED(ret, True);
2356         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2357
2358         /* Unlock the first process lock, then check this was the WRITE lock that was
2359                 removed. */
2360
2361         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2362               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2363
2364         EXPECTED(ret, True);
2365         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2366
2367         /* Unlock the process 2 lock. */
2368         cli_unlock(cli2, fnum2, 0, 4);
2369
2370         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2371
2372         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2373                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2374                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2375
2376         EXPECTED(ret, True);
2377         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2378
2379         /* Ensure the next unlock fails. */
2380         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2381         EXPECTED(ret, False);
2382         printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2383
2384         /* Ensure connection 2 can get a write lock. */
2385         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2386         ret = NT_STATUS_IS_OK(status);
2387         EXPECTED(ret, True);
2388
2389         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2390
2391
2392  fail:
2393         cli_close(cli1, fnum1);
2394         cli_close(cli2, fnum2);
2395         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2396         if (!torture_close_connection(cli1)) {
2397                 correct = False;
2398         }
2399         if (!torture_close_connection(cli2)) {
2400                 correct = False;
2401         }
2402
2403         printf("finished locktest5\n");
2404
2405         return correct;
2406 }
2407
2408 /*
2409   tries the unusual lockingX locktype bits
2410 */
2411 static bool run_locktest6(int dummy)
2412 {
2413         static struct cli_state *cli;
2414         const char *fname[1] = { "\\lock6.txt" };
2415         int i;
2416         uint16_t fnum;
2417         NTSTATUS status;
2418
2419         if (!torture_open_connection(&cli, 0)) {
2420                 return False;
2421         }
2422
2423         smbXcli_conn_set_sockopt(cli->conn, sockops);
2424
2425         printf("starting locktest6\n");
2426
2427         for (i=0;i<1;i++) {
2428                 printf("Testing %s\n", fname[i]);
2429
2430                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2431
2432                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2433                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2434                 cli_close(cli, fnum);
2435                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2436
2437                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2438                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2439                 cli_close(cli, fnum);
2440                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2441
2442                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2443         }
2444
2445         torture_close_connection(cli);
2446
2447         printf("finished locktest6\n");
2448         return True;
2449 }
2450
2451 static bool run_locktest7(int dummy)
2452 {
2453         struct cli_state *cli1;
2454         const char *fname = "\\lockt7.lck";
2455         uint16_t fnum1;
2456         char buf[200];
2457         bool correct = False;
2458         size_t nread;
2459         NTSTATUS status;
2460
2461         if (!torture_open_connection(&cli1, 0)) {
2462                 return False;
2463         }
2464
2465         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2466
2467         printf("starting locktest7\n");
2468
2469         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2470
2471         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2472
2473         memset(buf, 0, sizeof(buf));
2474
2475         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2476                               NULL);
2477         if (!NT_STATUS_IS_OK(status)) {
2478                 printf("Failed to create file: %s\n", nt_errstr(status));
2479                 goto fail;
2480         }
2481
2482         cli_setpid(cli1, 1);
2483
2484         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2485         if (!NT_STATUS_IS_OK(status)) {
2486                 printf("Unable to apply read lock on range 130:4, "
2487                        "error was %s\n", nt_errstr(status));
2488                 goto fail;
2489         } else {
2490                 printf("pid1 successfully locked range 130:4 for READ\n");
2491         }
2492
2493         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2494         if (!NT_STATUS_IS_OK(status)) {
2495                 printf("pid1 unable to read the range 130:4, error was %s\n",
2496                       nt_errstr(status));
2497                 goto fail;
2498         } else if (nread != 4) {
2499                 printf("pid1 unable to read the range 130:4, "
2500                        "recv %ld req %d\n", (unsigned long)nread, 4);
2501                 goto fail;
2502         } else {
2503                 printf("pid1 successfully read the range 130:4\n");
2504         }
2505
2506         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2507         if (!NT_STATUS_IS_OK(status)) {
2508                 printf("pid1 unable to write to the range 130:4, error was "
2509                        "%s\n", nt_errstr(status));
2510                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2511                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2512                         goto fail;
2513                 }
2514         } else {
2515                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2516                 goto fail;
2517         }
2518
2519         cli_setpid(cli1, 2);
2520
2521         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2522         if (!NT_STATUS_IS_OK(status)) {
2523                 printf("pid2 unable to read the range 130:4, error was %s\n",
2524                       nt_errstr(status));
2525                 goto fail;
2526         } else if (nread != 4) {
2527                 printf("pid2 unable to read the range 130:4, "
2528                        "recv %ld req %d\n", (unsigned long)nread, 4);
2529                 goto fail;
2530         } else {
2531                 printf("pid2 successfully read the range 130:4\n");
2532         }
2533
2534         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2535         if (!NT_STATUS_IS_OK(status)) {
2536                 printf("pid2 unable to write to the range 130:4, error was "
2537                        "%s\n", nt_errstr(status));
2538                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2539                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2540                         goto fail;
2541                 }
2542         } else {
2543                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2544                 goto fail;
2545         }
2546
2547         cli_setpid(cli1, 1);
2548         cli_unlock(cli1, fnum1, 130, 4);
2549
2550         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2551         if (!NT_STATUS_IS_OK(status)) {
2552                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2553                 goto fail;
2554         } else {
2555                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2556         }
2557
2558         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2559         if (!NT_STATUS_IS_OK(status)) {
2560                 printf("pid1 unable to read the range 130:4, error was %s\n",
2561                       nt_errstr(status));
2562                 goto fail;
2563         } else if (nread != 4) {
2564                 printf("pid1 unable to read the range 130:4, "
2565                        "recv %ld req %d\n", (unsigned long)nread, 4);
2566                 goto fail;
2567         } else {
2568                 printf("pid1 successfully read the range 130:4\n");
2569         }
2570
2571         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2572         if (!NT_STATUS_IS_OK(status)) {
2573                 printf("pid1 unable to write to the range 130:4, error was "
2574                        "%s\n", nt_errstr(status));
2575                 goto fail;
2576         } else {
2577                 printf("pid1 successfully wrote to the range 130:4\n");
2578         }
2579
2580         cli_setpid(cli1, 2);
2581
2582         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2583         if (!NT_STATUS_IS_OK(status)) {
2584                 printf("pid2 unable to read the range 130:4, error was "
2585                        "%s\n", nt_errstr(status));
2586                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2587                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2588                         goto fail;
2589                 }
2590         } else {
2591                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2592                        (unsigned long)nread);
2593                 goto fail;
2594         }
2595
2596         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2597         if (!NT_STATUS_IS_OK(status)) {
2598                 printf("pid2 unable to write to the range 130:4, error was "
2599                        "%s\n", nt_errstr(status));
2600                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2601                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2602                         goto fail;
2603                 }
2604         } else {
2605                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2606                 goto fail;
2607         }
2608
2609         cli_unlock(cli1, fnum1, 130, 0);
2610         correct = True;
2611
2612 fail:
2613         cli_close(cli1, fnum1);
2614         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2615         torture_close_connection(cli1);
2616
2617         printf("finished locktest7\n");
2618         return correct;
2619 }
2620
2621 /*
2622  * This demonstrates a problem with our use of GPFS share modes: A file
2623  * descriptor sitting in the pending close queue holding a GPFS share mode
2624  * blocks opening a file another time. Happens with Word 2007 temp files.
2625  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2626  * open is denied with NT_STATUS_SHARING_VIOLATION.
2627  */
2628
2629 static bool run_locktest8(int dummy)
2630 {
2631         struct cli_state *cli1;
2632         const char *fname = "\\lockt8.lck";
2633         uint16_t fnum1, fnum2;
2634         char buf[200];
2635         bool correct = False;
2636         NTSTATUS status;
2637
2638         if (!torture_open_connection(&cli1, 0)) {
2639                 return False;
2640         }
2641
2642         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2643
2644         printf("starting locktest8\n");
2645
2646         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2647
2648         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2649                           &fnum1);
2650         if (!NT_STATUS_IS_OK(status)) {
2651                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2652                 return false;
2653         }
2654
2655         memset(buf, 0, sizeof(buf));
2656
2657         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2658         if (!NT_STATUS_IS_OK(status)) {
2659                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2660                           nt_errstr(status));
2661                 goto fail;
2662         }
2663
2664         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2665         if (!NT_STATUS_IS_OK(status)) {
2666                 printf("Unable to apply read lock on range 1:1, error was "
2667                        "%s\n", nt_errstr(status));
2668                 goto fail;
2669         }
2670
2671         status = cli_close(cli1, fnum1);
2672         if (!NT_STATUS_IS_OK(status)) {
2673                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2674                 goto fail;
2675         }
2676
2677         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2678         if (!NT_STATUS_IS_OK(status)) {
2679                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2680                           nt_errstr(status));
2681                 goto fail;
2682         }
2683
2684         correct = true;
2685
2686 fail:
2687         cli_close(cli1, fnum1);
2688         cli_close(cli1, fnum2);
2689         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2690         torture_close_connection(cli1);
2691
2692         printf("finished locktest8\n");
2693         return correct;
2694 }
2695
2696 /*
2697  * This test is designed to be run in conjunction with
2698  * external NFS or POSIX locks taken in the filesystem.
2699  * It checks that the smbd server will block until the
2700  * lock is released and then acquire it. JRA.
2701  */
2702
2703 static bool got_alarm;
2704 static struct cli_state *alarm_cli;
2705
2706 static void alarm_handler(int dummy)
2707 {
2708         got_alarm = True;
2709 }
2710
2711 static void alarm_handler_parent(int dummy)
2712 {
2713         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2714 }
2715
2716 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2717 {
2718         int fd;
2719         char c = '\0';
2720         struct flock lock;
2721         const char *local_pathname = NULL;
2722         int ret;
2723
2724         local_pathname = talloc_asprintf(talloc_tos(),
2725                         "%s/%s", local_path, fname);
2726         if (!local_pathname) {
2727                 printf("child: alloc fail\n");
2728                 exit(1);
2729         }
2730
2731         unlink(local_pathname);
2732         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2733         if (fd == -1) {
2734                 printf("child: open of %s failed %s.\n",
2735                         local_pathname, strerror(errno));
2736                 exit(1);
2737         }
2738
2739         /* Now take a fcntl lock. */
2740         lock.l_type = F_WRLCK;
2741         lock.l_whence = SEEK_SET;
2742         lock.l_start = 0;
2743         lock.l_len = 4;
2744         lock.l_pid = getpid();
2745
2746         ret = fcntl(fd,F_SETLK,&lock);
2747         if (ret == -1) {
2748                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2749                         local_pathname, strerror(errno));
2750                 exit(1);
2751         } else {
2752                 printf("child: got lock 0:4 on file %s.\n",
2753                         local_pathname );
2754                 fflush(stdout);
2755         }
2756
2757         CatchSignal(SIGALRM, alarm_handler);
2758         alarm(5);
2759         /* Signal the parent. */
2760         if (write(write_fd, &c, 1) != 1) {
2761                 printf("child: start signal fail %s.\n",
2762                         strerror(errno));
2763                 exit(1);
2764         }
2765         alarm(0);
2766
2767         alarm(10);
2768         /* Wait for the parent to be ready. */
2769         if (read(read_fd, &c, 1) != 1) {
2770                 printf("child: reply signal fail %s.\n",
2771                         strerror(errno));
2772                 exit(1);
2773         }
2774         alarm(0);
2775
2776         sleep(5);
2777         close(fd);
2778         printf("child: released lock 0:4 on file %s.\n",
2779                 local_pathname );
2780         fflush(stdout);
2781         exit(0);
2782 }
2783
2784 static bool _run_locktest9X(const char *fname, int timeout)
2785 {
2786         struct cli_state *cli1;
2787         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2788         uint16_t fnum;
2789         bool correct = False;
2790         int pipe_in[2], pipe_out[2];
2791         pid_t child_pid;
2792         char c = '\0';
2793         int ret;
2794         struct timeval start;
2795         double seconds;
2796         NTSTATUS status;
2797
2798         printf("starting locktest9X: %s\n", fname);
2799
2800         if (local_path == NULL) {
2801                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2802                 return false;
2803         }
2804
2805         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2806                 return false;
2807         }
2808
2809         child_pid = fork();
2810         if (child_pid == -1) {
2811                 return false;
2812         }
2813
2814         if (child_pid == 0) {
2815                 /* Child. */
2816                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2817                 exit(0);
2818         }
2819
2820         close(pipe_out[0]);
2821         close(pipe_in[1]);
2822         pipe_out[0] = -1;
2823         pipe_in[1] = -1;
2824
2825         /* Parent. */
2826         ret = read(pipe_in[0], &c, 1);
2827         if (ret != 1) {
2828                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2829                         strerror(errno));
2830                 return false;
2831         }
2832
2833         if (!torture_open_connection(&cli1, 0)) {
2834                 return false;
2835         }
2836
2837         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2838
2839         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2840                           &fnum);
2841         if (!NT_STATUS_IS_OK(status)) {
2842                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2843                 return false;
2844         }
2845
2846         /* Ensure the child has the lock. */
2847         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2848         if (NT_STATUS_IS_OK(status)) {
2849                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2850                 goto fail;
2851         } else {
2852                 d_printf("Child has the lock.\n");
2853         }
2854
2855         /* Tell the child to wait 5 seconds then exit. */
2856         ret = write(pipe_out[1], &c, 1);
2857         if (ret != 1) {
2858                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2859                         strerror(errno));
2860                 goto fail;
2861         }
2862
2863         /* Wait 20 seconds for the lock. */
2864         alarm_cli = cli1;
2865         CatchSignal(SIGALRM, alarm_handler_parent);
2866         alarm(20);
2867
2868         start = timeval_current();
2869
2870         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2871         if (!NT_STATUS_IS_OK(status)) {
2872                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2873                        "%s\n", nt_errstr(status));
2874                 goto fail_nofd;
2875         }
2876         alarm(0);
2877
2878         seconds = timeval_elapsed(&start);
2879
2880         printf("Parent got the lock after %.2f seconds.\n",
2881                 seconds);
2882
2883         status = cli_close(cli1, fnum);
2884         if (!NT_STATUS_IS_OK(status)) {
2885                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2886                 goto fail;
2887         }
2888
2889         correct = true;
2890
2891 fail:
2892         cli_close(cli1, fnum);
2893         torture_close_connection(cli1);
2894
2895 fail_nofd:
2896
2897         printf("finished locktest9X: %s\n", fname);
2898         return correct;
2899 }
2900
2901 static bool run_locktest9a(int dummy)
2902 {
2903         return _run_locktest9X("lock9a.dat", -1);
2904 }
2905
2906 static bool run_locktest9b(int dummy)
2907 {
2908         return _run_locktest9X("lock9b.dat", 10000);
2909 }
2910
2911 struct locktest10_state {
2912         bool ok;
2913         bool done;
2914 };
2915
2916 static void locktest10_lockingx_done(struct tevent_req *subreq);
2917 static void locktest10_read_andx_done(struct tevent_req *subreq);
2918
2919 static bool run_locktest10(int dummy)
2920 {
2921         struct tevent_context *ev = NULL;
2922         struct cli_state *cli1 = NULL;
2923         struct cli_state *cli2 = NULL;
2924         struct smb1_lock_element lck = { 0 };
2925         struct tevent_req *reqs[2] = { NULL };
2926         struct tevent_req *smbreqs[2] = { NULL };
2927         const char fname[] = "\\lockt10.lck";
2928         uint16_t fnum1, fnum2;
2929         bool ret = false;
2930         bool ok;
2931         uint8_t data = 1;
2932         struct locktest10_state state = { .ok = true };
2933         NTSTATUS status;
2934
2935         printf("starting locktest10\n");
2936
2937         ev = samba_tevent_context_init(NULL);
2938         if (ev == NULL) {
2939                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2940                 goto done;
2941         }
2942
2943         ok = torture_open_connection(&cli1, 0);
2944         if (!ok) {
2945                 goto done;
2946         }
2947         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2948
2949         ok = torture_open_connection(&cli2, 1);
2950         if (!ok) {
2951                 goto done;
2952         }
2953         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2954
2955         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2956         if (!NT_STATUS_IS_OK(status)) {
2957                 d_fprintf(stderr,
2958                           "cli_openx failed: %s\n",
2959                           nt_errstr(status));
2960                 goto done;
2961         }
2962
2963         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2964         if (!NT_STATUS_IS_OK(status)) {
2965                 d_fprintf(stderr,
2966                           "cli_writeall failed: %s\n",
2967                           nt_errstr(status));
2968                 goto done;
2969         }
2970
2971         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2972         if (!NT_STATUS_IS_OK(status)) {
2973                 d_fprintf(stderr,
2974                           "cli_openx failed: %s\n",
2975                           nt_errstr(status));
2976                 goto done;
2977         }
2978
2979         status = cli_locktype(
2980                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2981         if (!NT_STATUS_IS_OK(status)) {
2982                 d_fprintf(stderr,
2983                           "cli_locktype failed: %s\n",
2984                           nt_errstr(status));
2985                 goto done;
2986         }
2987
2988         lck = (struct smb1_lock_element) {
2989                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2990         };
2991
2992         reqs[0] = cli_lockingx_create(
2993                 ev,                             /* mem_ctx */
2994                 ev,                             /* tevent_context */
2995                 cli1,                           /* cli */
2996                 fnum1,                          /* fnum */
2997                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2998                 0,                              /* newoplocklevel */
2999                 1,                              /* timeout */
3000                 0,                              /* num_unlocks */
3001                 NULL,                           /* unlocks */
3002                 1,                              /* num_locks */
3003                 &lck,                           /* locks */
3004                 &smbreqs[0]);                   /* psmbreq */
3005         if (reqs[0] == NULL) {
3006                 d_fprintf(stderr, "cli_lockingx_create failed\n");
3007                 goto done;
3008         }
3009         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3010
3011         reqs[1] = cli_read_andx_create(
3012                 ev,             /* mem_ctx */
3013                 ev,             /* ev */
3014                 cli1,           /* cli */
3015                 fnum1,          /* fnum */
3016                 0,              /* offset */
3017                 1,              /* size */
3018                 &smbreqs[1]);   /* psmbreq */
3019         if (reqs[1] == NULL) {
3020                 d_fprintf(stderr, "cli_read_andx_create failed\n");
3021                 goto done;
3022         }
3023         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3024
3025         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3026         if (!NT_STATUS_IS_OK(status)) {
3027                 d_fprintf(stderr,
3028                           "smb1cli_req_chain_submit failed: %s\n",
3029                           nt_errstr(status));
3030                 goto done;
3031         }
3032
3033         while (!state.done) {
3034                 tevent_loop_once(ev);
3035         }
3036
3037         torture_close_connection(cli1);
3038
3039         if (state.ok) {
3040                 ret = true;
3041         }
3042 done:
3043         return ret;
3044 }
3045
3046 static void locktest10_lockingx_done(struct tevent_req *subreq)
3047 {
3048         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3049         NTSTATUS status;
3050
3051         status = cli_lockingx_recv(subreq);
3052         TALLOC_FREE(subreq);
3053
3054         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3055                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3056                 state->ok = false;
3057         }
3058 }
3059
3060 static void locktest10_read_andx_done(struct tevent_req *subreq)
3061 {
3062         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3063         ssize_t received = -1;
3064         uint8_t *rcvbuf = NULL;
3065         NTSTATUS status;
3066
3067         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3068
3069         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3070                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3071                 state->ok = false;
3072         }
3073
3074         state->done = true;
3075         TALLOC_FREE(subreq);
3076 }
3077
3078 static bool run_locktest11(int dummy)
3079 {
3080         struct cli_state *cli1;
3081         const char *fname = "\\lockt11.lck";
3082         NTSTATUS status;
3083         uint16_t fnum;
3084         bool ret = false;
3085
3086         if (!torture_open_connection(&cli1, 0)) {
3087                 return false;
3088         }
3089
3090         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3091
3092         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3093
3094         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3095         if (!NT_STATUS_IS_OK(status)) {
3096                 d_fprintf(stderr,
3097                           "cli_openx returned %s\n",
3098                           nt_errstr(status));
3099                 return false;
3100         }
3101
3102         /*
3103          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3104          * returns NT_STATUS_OK
3105          */
3106
3107         status = cli_lockingx(
3108                 cli1,                           /* cli */
3109                 fnum,                           /* fnum */
3110                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3111                 0,                              /* newoplocklevel */
3112                 0,                              /* timeout */
3113                 0,                              /* num_unlocks */
3114                 NULL,                           /* unlocks */
3115                 0,                              /* num_locks */
3116                 NULL);                          /* locks */
3117
3118         if (!NT_STATUS_IS_OK(status)) {
3119                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3120                 goto fail;
3121         }
3122
3123         ret = true;
3124 fail:
3125         cli_close(cli1, fnum);
3126         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3127
3128         return ret;
3129 }
3130
3131 struct deferred_close_state {
3132         struct tevent_context *ev;
3133         struct cli_state *cli;
3134         uint16_t fnum;
3135 };
3136
3137 static void deferred_close_waited(struct tevent_req *subreq);
3138 static void deferred_close_done(struct tevent_req *subreq);
3139
3140 static struct tevent_req *deferred_close_send(
3141         TALLOC_CTX *mem_ctx,
3142         struct tevent_context *ev,
3143         int wait_secs,
3144         struct cli_state *cli,
3145         uint16_t fnum)
3146 {
3147         struct tevent_req *req = NULL, *subreq = NULL;
3148         struct deferred_close_state *state = NULL;
3149         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3150
3151         req = tevent_req_create(
3152                 mem_ctx, &state, struct deferred_close_state);
3153         if (req == NULL) {
3154                 return NULL;
3155         }
3156         state->ev = ev;
3157         state->cli = cli;
3158         state->fnum = fnum;
3159
3160         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3161         if (tevent_req_nomem(subreq, req)) {
3162                 return tevent_req_post(req, ev);
3163         }
3164         tevent_req_set_callback(subreq, deferred_close_waited, req);
3165         return req;
3166 }
3167
3168 static void deferred_close_waited(struct tevent_req *subreq)
3169 {
3170         struct tevent_req *req = tevent_req_callback_data(
3171                 subreq, struct tevent_req);
3172         struct deferred_close_state *state = tevent_req_data(
3173                 req, struct deferred_close_state);
3174         bool ok;
3175
3176         ok = tevent_wakeup_recv(subreq);
3177         TALLOC_FREE(subreq);
3178         if (!ok) {
3179                 tevent_req_oom(req);
3180                 return;
3181         }
3182
3183         subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3184         if (tevent_req_nomem(subreq, req)) {
3185                 return;
3186         }
3187         tevent_req_set_callback(subreq, deferred_close_done, req);
3188 }
3189
3190 static void deferred_close_done(struct tevent_req *subreq)
3191 {
3192         NTSTATUS status = cli_close_recv(subreq);
3193         tevent_req_simple_finish_ntstatus(subreq, status);
3194 }
3195
3196 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3197 {
3198         return tevent_req_simple_recv_ntstatus(req);
3199 }
3200
3201 struct lockread_state {
3202         struct smb1_lock_element lck;
3203         struct tevent_req *reqs[2];
3204         struct tevent_req *smbreqs[2];
3205         NTSTATUS lock_status;
3206         NTSTATUS read_status;
3207         uint8_t *readbuf;
3208 };
3209
3210 static void lockread_lockingx_done(struct tevent_req *subreq);
3211 static void lockread_read_andx_done(struct tevent_req *subreq);
3212
3213 static struct tevent_req *lockread_send(
3214         TALLOC_CTX *mem_ctx,
3215         struct tevent_context *ev,
3216         struct cli_state *cli,
3217         uint16_t fnum)
3218 {
3219         struct tevent_req *req = NULL;
3220         struct lockread_state *state = NULL;
3221         NTSTATUS status;
3222
3223         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3224         if (req == NULL) {
3225                 return NULL;
3226         }
3227
3228         state->lck = (struct smb1_lock_element) {
3229                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3230         };
3231
3232         state->reqs[0] = cli_lockingx_create(
3233                 ev,                             /* mem_ctx */
3234                 ev,                             /* tevent_context */
3235                 cli,                            /* cli */
3236                 fnum,                           /* fnum */
3237                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3238                 0,                              /* newoplocklevel */
3239                 10000,                          /* timeout */
3240                 0,                              /* num_unlocks */
3241                 NULL,                           /* unlocks */
3242                 1,                              /* num_locks */
3243                 &state->lck,                    /* locks */
3244                 &state->smbreqs[0]);            /* psmbreq */
3245         if (tevent_req_nomem(state->reqs[0], req)) {
3246                 return tevent_req_post(req, ev);
3247         }
3248         tevent_req_set_callback(
3249                 state->reqs[0], lockread_lockingx_done, req);
3250
3251         state->reqs[1] = cli_read_andx_create(
3252                 ev,             /* mem_ctx */
3253                 ev,             /* ev */
3254                 cli,            /* cli */
3255                 fnum,           /* fnum */
3256                 0,              /* offset */
3257                 1,              /* size */
3258                 &state->smbreqs[1]);    /* psmbreq */
3259         if (tevent_req_nomem(state->reqs[1], req)) {
3260                 return tevent_req_post(req, ev);
3261         }
3262         tevent_req_set_callback(
3263                 state->reqs[1], lockread_read_andx_done, req);
3264
3265         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3266         if (tevent_req_nterror(req, status)) {
3267                 return tevent_req_post(req, ev);
3268         }
3269         return req;
3270 }
3271
3272 static void lockread_lockingx_done(struct tevent_req *subreq)
3273 {
3274         struct tevent_req *req = tevent_req_callback_data(
3275                 subreq, struct tevent_req);
3276         struct lockread_state *state = tevent_req_data(
3277                 req, struct lockread_state);
3278         state->lock_status = cli_lockingx_recv(subreq);
3279         TALLOC_FREE(subreq);
3280         d_fprintf(stderr,
3281                   "lockingx returned %s\n",
3282                   nt_errstr(state->lock_status));
3283 }
3284
3285 static void lockread_read_andx_done(struct tevent_req *subreq)
3286 {
3287         struct tevent_req *req = tevent_req_callback_data(
3288                 subreq, struct tevent_req);
3289         struct lockread_state *state = tevent_req_data(
3290                 req, struct lockread_state);
3291         ssize_t received = -1;
3292         uint8_t *rcvbuf = NULL;
3293
3294         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3295
3296         d_fprintf(stderr,
3297                   "read returned %s\n",
3298                   nt_errstr(state->read_status));
3299
3300         if (!NT_STATUS_IS_OK(state->read_status)) {
3301                 TALLOC_FREE(subreq);
3302                 tevent_req_done(req);
3303                 return;
3304         }
3305
3306         if (received > 0) {
3307                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3308                 TALLOC_FREE(subreq);
3309                 if (tevent_req_nomem(state->readbuf, req)) {
3310                         return;
3311                 }
3312         }
3313         TALLOC_FREE(subreq);
3314         tevent_req_done(req);
3315 }
3316
3317 static NTSTATUS lockread_recv(
3318         struct tevent_req *req,
3319         NTSTATUS *lock_status,
3320         NTSTATUS *read_status,
3321         TALLOC_CTX *mem_ctx,
3322         uint8_t **read_buf)
3323 {
3324         struct lockread_state *state = tevent_req_data(
3325                 req, struct lockread_state);
3326         NTSTATUS status;
3327
3328         if (tevent_req_is_nterror(req, &status)) {
3329                 return status;
3330         }
3331
3332         *lock_status = state->lock_status;
3333         *read_status = state->read_status;
3334         if (state->readbuf != NULL) {
3335                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3336         } else {
3337                 *read_buf = NULL;
3338         }
3339
3340         return NT_STATUS_OK;
3341 }
3342
3343 struct lock12_state {
3344         uint8_t dummy;
3345 };
3346
3347 static void lock12_closed(struct tevent_req *subreq);
3348 static void lock12_read(struct tevent_req *subreq);
3349
3350 static struct tevent_req *lock12_send(
3351         TALLOC_CTX *mem_ctx,
3352         struct tevent_context *ev,
3353         struct cli_state *cli,
3354         uint16_t fnum1,
3355         uint16_t fnum2)
3356 {
3357         struct tevent_req *req = NULL, *subreq = NULL;
3358         struct lock12_state *state = NULL;
3359
3360         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3361         if (req == NULL) {
3362                 return NULL;
3363         }
3364
3365         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3366         if (tevent_req_nomem(subreq, req)) {
3367                 return tevent_req_post(req, ev);
3368         }
3369         tevent_req_set_callback(subreq, lock12_closed, req);
3370
3371         subreq = lockread_send(state, ev, cli, fnum2);
3372         if (tevent_req_nomem(subreq, req)) {
3373                 return tevent_req_post(req, ev);
3374         }
3375         tevent_req_set_callback(subreq, lock12_read, req);
3376
3377         return req;
3378 }
3379
3380 static void lock12_closed(struct tevent_req *subreq)
3381 {
3382         struct tevent_req *req = tevent_req_callback_data(
3383                 subreq, struct tevent_req);
3384         NTSTATUS status;
3385
3386         status = deferred_close_recv(subreq);
3387         TALLOC_FREE(subreq);
3388         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3389         if (tevent_req_nterror(req, status)) {
3390                 return;
3391         }
3392 }
3393
3394 static void lock12_read(struct tevent_req *subreq)
3395 {
3396         struct tevent_req *req = tevent_req_callback_data(
3397                 subreq, struct tevent_req);
3398         struct lock12_state *state = tevent_req_data(
3399                 req, struct lock12_state);
3400         NTSTATUS status, lock_status, read_status;
3401         uint8_t *buf = NULL;
3402
3403         status = lockread_recv(
3404                 subreq, &lock_status, &read_status, state, &buf);
3405         TALLOC_FREE(subreq);
3406         if (tevent_req_nterror(req, status) ||
3407             tevent_req_nterror(req, lock_status) ||
3408             tevent_req_nterror(req, read_status)) {
3409                 return;
3410         }
3411         tevent_req_done(req);
3412 }
3413
3414 static NTSTATUS lock12_recv(struct tevent_req *req)
3415
3416 {
3417         NTSTATUS status;
3418
3419         if (tevent_req_is_nterror(req, &status)) {
3420                 return status;
3421         }
3422         return NT_STATUS_OK;
3423 }
3424
3425 static bool run_locktest12(int dummy)
3426 {
3427         struct tevent_context *ev = NULL;
3428         struct tevent_req *req = NULL;
3429         struct cli_state *cli = NULL;
3430         const char fname[] = "\\lockt12.lck";
3431         uint16_t fnum1, fnum2;
3432         bool ret = false;
3433         bool ok;
3434         uint8_t data = 1;
3435         NTSTATUS status;
3436
3437         printf("starting locktest12\n");
3438
3439         ev = samba_tevent_context_init(NULL);
3440         if (ev == NULL) {
3441                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3442                 goto done;
3443         }
3444
3445         ok = torture_open_connection(&cli, 0);
3446         if (!ok) {
3447                 goto done;
3448         }
3449         smbXcli_conn_set_sockopt(cli->conn, sockops);
3450
3451         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3452         if (!NT_STATUS_IS_OK(status)) {
3453                 d_fprintf(stderr,
3454                           "cli_openx failed: %s\n",
3455                           nt_errstr(status));
3456                 goto done;
3457         }
3458
3459         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3460         if (!NT_STATUS_IS_OK(status)) {
3461                 d_fprintf(stderr,
3462                           "cli_openx failed: %s\n",
3463                           nt_errstr(status));
3464                 goto done;
3465         }
3466
3467         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3468         if (!NT_STATUS_IS_OK(status)) {
3469                 d_fprintf(stderr,
3470                           "cli_writeall failed: %s\n",
3471                           nt_errstr(status));
3472                 goto done;
3473         }
3474
3475         status = cli_locktype(
3476                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3477         if (!NT_STATUS_IS_OK(status)) {
3478                 d_fprintf(stderr,
3479                           "cli_locktype failed: %s\n",
3480                           nt_errstr(status));
3481                 goto done;
3482         }
3483
3484         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3485         if (req == NULL) {
3486                 d_fprintf(stderr, "lock12_send failed\n");
3487                 goto done;
3488         }
3489
3490         ok = tevent_req_poll_ntstatus(req, ev, &status);
3491         if (!ok) {
3492                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3493                 goto done;
3494         }
3495
3496         if (!NT_STATUS_IS_OK(status)) {
3497                 d_fprintf(stderr,
3498                           "tevent_req_poll_ntstatus returned %s\n",
3499                           nt_errstr(status));
3500                 goto done;
3501         }
3502
3503         status = lock12_recv(req);
3504         if (!NT_STATUS_IS_OK(status)) {
3505                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3506                 goto done;
3507         }
3508
3509         ret = true;
3510 done:
3511         if (cli != NULL) {
3512                 torture_close_connection(cli);
3513         }
3514         return ret;
3515 }
3516
3517 struct lock_ntcancel_state {
3518         struct timeval start;
3519         struct smb1_lock_element lck;
3520         struct tevent_req *subreq;
3521 };
3522
3523 static void lock_ntcancel_waited(struct tevent_req *subreq);
3524 static void lock_ntcancel_done(struct tevent_req *subreq);
3525
3526 static struct tevent_req *lock_ntcancel_send(
3527         TALLOC_CTX *mem_ctx,
3528         struct tevent_context *ev,
3529         struct cli_state *cli,
3530         uint16_t fnum)
3531 {
3532         struct tevent_req *req = NULL, *subreq = NULL;
3533         struct lock_ntcancel_state *state = NULL;
3534
3535         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3536         if (req == NULL) {
3537                 return NULL;
3538         }
3539         state->lck = (struct smb1_lock_element) {
3540                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3541         };
3542         state->start = timeval_current();
3543
3544         state->subreq = cli_lockingx_send(
3545                 state,                          /* mem_ctx */
3546                 ev,                             /* tevent_context */
3547                 cli,                            /* cli */
3548                 fnum,                           /* fnum */
3549                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3550                 0,                              /* newoplocklevel */
3551                 10000,                          /* timeout */
3552                 0,                              /* num_unlocks */
3553                 NULL,                           /* unlocks */
3554                 1,                              /* num_locks */
3555                 &state->lck);                   /* locks */
3556         if (tevent_req_nomem(state->subreq, req)) {
3557                 return tevent_req_post(req, ev);
3558         }
3559         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3560
3561         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3562         if (tevent_req_nomem(subreq, req)) {
3563                 return tevent_req_post(req, ev);
3564         }
3565         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3566         return req;
3567 }
3568
3569 static void lock_ntcancel_waited(struct tevent_req *subreq)
3570 {
3571         struct tevent_req *req = tevent_req_callback_data(
3572                 subreq, struct tevent_req);
3573         struct lock_ntcancel_state *state = tevent_req_data(
3574                 req, struct lock_ntcancel_state);
3575         bool ok;
3576
3577         ok = tevent_wakeup_recv(subreq);
3578         TALLOC_FREE(subreq);
3579         if (!ok) {
3580                 tevent_req_oom(req);
3581                 return;
3582         }
3583
3584         ok = tevent_req_cancel(state->subreq);
3585         if (!ok) {
3586                 d_fprintf(stderr, "Could not cancel subreq\n");
3587                 tevent_req_oom(req);
3588                 return;
3589         }
3590 }
3591
3592 static void lock_ntcancel_done(struct tevent_req *subreq)
3593 {
3594         struct tevent_req *req = tevent_req_callback_data(
3595                 subreq, struct tevent_req);
3596         struct lock_ntcancel_state *state = tevent_req_data(
3597                 req, struct lock_ntcancel_state);
3598         NTSTATUS status;
3599         double elapsed;
3600
3601         status = cli_lockingx_recv(subreq);
3602         TALLOC_FREE(subreq);
3603
3604         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3605                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3606                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3607                 return;
3608         }
3609
3610         elapsed = timeval_elapsed(&state->start);
3611
3612         if (elapsed > 3) {
3613                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3614                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3615                 return;
3616         }
3617
3618         tevent_req_done(req);
3619 }
3620
3621 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3622 {
3623         return tevent_req_simple_recv_ntstatus(req);
3624 }
3625
3626 static bool run_locktest13(int dummy)
3627 {
3628         struct tevent_context *ev = NULL;
3629         struct tevent_req *req = NULL;
3630         struct cli_state *cli = NULL;
3631         const char fname[] = "\\lockt13.lck";
3632         uint16_t fnum1, fnum2;
3633         bool ret = false;
3634         bool ok;
3635         uint8_t data = 1;
3636         NTSTATUS status;
3637
3638         printf("starting locktest13\n");
3639
3640         ev = samba_tevent_context_init(NULL);
3641         if (ev == NULL) {
3642                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3643                 goto done;
3644         }
3645
3646         ok = torture_open_connection(&cli, 0);
3647         if (!ok) {
3648                 goto done;
3649         }
3650         smbXcli_conn_set_sockopt(cli->conn, sockops);
3651
3652         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3653         if (!NT_STATUS_IS_OK(status)) {
3654                 d_fprintf(stderr,
3655                           "cli_openx failed: %s\n",
3656                           nt_errstr(status));
3657                 goto done;
3658         }
3659
3660         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3661         if (!NT_STATUS_IS_OK(status)) {
3662                 d_fprintf(stderr,
3663                           "cli_openx failed: %s\n",
3664                           nt_errstr(status));
3665                 goto done;
3666         }
3667
3668         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3669         if (!NT_STATUS_IS_OK(status)) {
3670                 d_fprintf(stderr,
3671                           "cli_writeall failed: %s\n",
3672                           nt_errstr(status));
3673                 goto done;
3674         }
3675
3676         status = cli_locktype(
3677                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3678         if (!NT_STATUS_IS_OK(status)) {
3679                 d_fprintf(stderr,
3680                           "cli_locktype failed: %s\n",
3681                           nt_errstr(status));
3682                 goto done;
3683         }
3684
3685         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3686         if (req == NULL) {
3687                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3688                 goto done;
3689         }
3690
3691         ok = tevent_req_poll_ntstatus(req, ev, &status);
3692         if (!ok) {
3693                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3694                 goto done;
3695         }
3696
3697         if (!NT_STATUS_IS_OK(status)) {
3698                 d_fprintf(stderr,
3699                           "tevent_req_poll_ntstatus returned %s\n",
3700                           nt_errstr(status));
3701                 goto done;
3702         }
3703
3704         status = lock_ntcancel_recv(req);
3705         if (!NT_STATUS_IS_OK(status)) {
3706                 d_fprintf(stderr,
3707                           "lock_ntcancel returned %s\n",
3708                           nt_errstr(status));
3709                 goto done;
3710         }
3711
3712         ret = true;
3713 done:
3714         if (cli != NULL) {
3715                 torture_close_connection(cli);
3716         }
3717         return ret;
3718 }
3719
3720 /*
3721 test whether fnums and tids open on one VC are available on another (a major
3722 security hole)
3723 */
3724 static bool run_fdpasstest(int dummy)
3725 {
3726         struct cli_state *cli1, *cli2;
3727         const char *fname = "\\fdpass.tst";
3728         uint16_t fnum1;
3729         char buf[1024];
3730         NTSTATUS status;
3731
3732         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3733                 return False;
3734         }
3735         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3736         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3737
3738         printf("starting fdpasstest\n");
3739
3740         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3741
3742         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3743                           &fnum1);
3744         if (!NT_STATUS_IS_OK(status)) {
3745                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3746                 return False;
3747         }
3748
3749         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3750                               13, NULL);
3751         if (!NT_STATUS_IS_OK(status)) {
3752                 printf("write failed (%s)\n", nt_errstr(status));
3753                 return False;
3754         }
3755
3756         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3757         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3758         cli_setpid(cli2, cli_getpid(cli1));
3759
3760         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3761                 printf("read succeeded! nasty security hole [%s]\n", buf);
3762                 return false;
3763         }
3764
3765         cli_close(cli1, fnum1);
3766         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3767
3768         torture_close_connection(cli1);
3769         torture_close_connection(cli2);
3770
3771         printf("finished fdpasstest\n");
3772         return True;
3773 }
3774
3775 static bool run_fdsesstest(int dummy)
3776 {
3777         struct cli_state *cli;
3778         uint16_t new_vuid;
3779         uint16_t saved_vuid;
3780         uint32_t new_cnum;
3781         uint32_t saved_cnum;
3782         const char *fname = "\\fdsess.tst";
3783         const char *fname1 = "\\fdsess1.tst";
3784         uint16_t fnum1;
3785         uint16_t fnum2;
3786         char buf[1024];
3787         bool ret = True;
3788         NTSTATUS status;
3789
3790         if (!torture_open_connection(&cli, 0))
3791                 return False;
3792         smbXcli_conn_set_sockopt(cli->conn, sockops);
3793
3794         if (!torture_cli_session_setup2(cli, &new_vuid))
3795                 return False;
3796
3797         saved_cnum = cli_state_get_tid(cli);
3798         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3799                 return False;
3800         new_cnum = cli_state_get_tid(cli);
3801         cli_state_set_tid(cli, saved_cnum);
3802
3803         printf("starting fdsesstest\n");
3804
3805         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3806         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3807
3808         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3809         if (!NT_STATUS_IS_OK(status)) {
3810                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3811                 return False;
3812         }
3813
3814         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3815                               NULL);
3816         if (!NT_STATUS_IS_OK(status)) {
3817                 printf("write failed (%s)\n", nt_errstr(status));
3818                 return False;
3819         }
3820
3821         saved_vuid = cli_state_get_uid(cli);
3822         cli_state_set_uid(cli, new_vuid);
3823
3824         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3825                 printf("read succeeded with different vuid! "
3826                        "nasty security hole [%s]\n", buf);
3827                 ret = false;
3828         }
3829         /* Try to open a file with different vuid, samba cnum. */
3830         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3831                 printf("create with different vuid, same cnum succeeded.\n");
3832                 cli_close(cli, fnum2);
3833                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3834         } else {
3835                 printf("create with different vuid, same cnum failed.\n");
3836                 printf("This will cause problems with service clients.\n");
3837                 ret = False;
3838         }
3839
3840         cli_state_set_uid(cli, saved_vuid);
3841
3842         /* Try with same vuid, different cnum. */
3843         cli_state_set_tid(cli, new_cnum);
3844
3845         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3846                 printf("read succeeded with different cnum![%s]\n", buf);
3847                 ret = false;
3848         }
3849
3850         cli_state_set_tid(cli, saved_cnum);
3851         cli_close(cli, fnum1);
3852         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3853
3854         torture_close_connection(cli);
3855
3856         printf("finished fdsesstest\n");
3857         return ret;
3858 }
3859
3860 /*
3861   This test checks that
3862
3863   1) the server does not allow an unlink on a file that is open
3864 */
3865 static bool run_unlinktest(int dummy)
3866 {
3867         struct cli_state *cli;
3868         const char *fname = "\\unlink.tst";
3869         uint16_t fnum;
3870         bool correct = True;
3871         NTSTATUS status;
3872
3873         if (!torture_open_connection(&cli, 0)) {
3874                 return False;
3875         }
3876
3877         smbXcli_conn_set_sockopt(cli->conn, sockops);
3878
3879         printf("starting unlink test\n");
3880
3881         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3882
3883         cli_setpid(cli, 1);
3884
3885         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3886         if (!NT_STATUS_IS_OK(status)) {
3887                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3888                 return False;
3889         }
3890
3891         status = cli_unlink(cli, fname,
3892                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3893         if (NT_STATUS_IS_OK(status)) {
3894                 printf("error: server allowed unlink on an open file\n");
3895                 correct = False;
3896         } else {
3897                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3898                                       NT_STATUS_SHARING_VIOLATION);
3899         }
3900
3901         cli_close(cli, fnum);
3902         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3903
3904         if (!torture_close_connection(cli)) {
3905                 correct = False;
3906         }
3907
3908         printf("unlink test finished\n");
3909
3910         return correct;
3911 }
3912
3913
3914 /*
3915 test how many open files this server supports on the one socket
3916 */
3917 static bool run_maxfidtest(int dummy)
3918 {
3919         struct cli_state *cli;
3920         fstring fname;
3921         uint16_t fnums[0x11000];
3922         int i;
3923         int retries=4;
3924         bool correct = True;
3925         NTSTATUS status;
3926
3927         cli = current_cli;
3928
3929         if (retries <= 0) {
3930                 printf("failed to connect\n");
3931                 return False;
3932         }
3933
3934         smbXcli_conn_set_sockopt(cli->conn, sockops);
3935
3936         for (i=0; i<0x11000; i++) {
3937                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3938                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3939                                   &fnums[i]);
3940                 if (!NT_STATUS_IS_OK(status)) {
3941                         printf("open of %s failed (%s)\n",
3942                                fname, nt_errstr(status));
3943                         printf("maximum fnum is %d\n", i);
3944                         break;
3945                 }
3946                 printf("%6d\r", i);
3947         }
3948         printf("%6d\n", i);
3949         i--;
3950
3951         printf("cleaning up\n");
3952         for (;i>=0;i--) {
3953                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3954                 cli_close(cli, fnums[i]);
3955
3956                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3957                 if (!NT_STATUS_IS_OK(status)) {
3958                         printf("unlink of %s failed (%s)\n",
3959                                fname, nt_errstr(status));
3960                         correct = False;
3961                 }
3962                 printf("%6d\r", i);
3963         }
3964         printf("%6d\n", 0);
3965
3966         printf("maxfid test finished\n");
3967         if (!torture_close_connection(cli)) {
3968                 correct = False;
3969         }
3970         return correct;
3971 }
3972
3973 /* generate a random buffer */
3974 static void rand_buf(char *buf, int len)
3975 {
3976         while (len--) {
3977                 *buf = (char)sys_random();
3978                 buf++;
3979         }
3980 }
3981
3982 /* send smb negprot commands, not reading the response */
3983 static bool run_negprot_nowait(int dummy)
3984 {
3985         struct tevent_context *ev;
3986         int i;
3987         struct cli_state *cli;
3988         bool correct = True;
3989
3990         printf("starting negprot nowait test\n");
3991
3992         ev = samba_tevent_context_init(talloc_tos());
3993         if (ev == NULL) {
3994                 return false;
3995         }
3996
3997         if (!(cli = open_nbt_connection())) {
3998                 TALLOC_FREE(ev);
3999                 return False;
4000         }
4001
4002         for (i=0;i<50000;i++) {
4003                 struct tevent_req *req;
4004
4005                 req = smbXcli_negprot_send(
4006                         ev,
4007                         ev,
4008                         cli->conn,
4009                         cli->timeout,
4010                         PROTOCOL_CORE,
4011                         PROTOCOL_NT1,
4012                         0,
4013                         NULL);
4014                 if (req == NULL) {
4015                         TALLOC_FREE(ev);
4016                         return false;
4017                 }
4018                 if (!tevent_req_poll(req, ev)) {
4019                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4020                                   strerror(errno));
4021                         TALLOC_FREE(ev);
4022                         return false;
4023                 }
4024                 TALLOC_FREE(req);
4025         }
4026
4027         if (torture_close_connection(cli)) {
4028                 correct = False;
4029         }
4030
4031         printf("finished negprot nowait test\n");
4032
4033         return correct;
4034 }
4035
4036 /* send smb negprot commands, not reading the response */
4037 static bool run_bad_nbt_session(int dummy)
4038 {
4039         struct nmb_name called, calling;
4040         struct sockaddr_storage ss;
4041         NTSTATUS status;
4042         int fd;
4043         bool ret;
4044
4045         printf("starting bad nbt session test\n");
4046
4047         make_nmb_name(&calling, myname, 0x0);
4048         make_nmb_name(&called , host, 0x20);
4049
4050         if (!resolve_name(host, &ss, 0x20, true)) {
4051                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4052                 return false;
4053         }
4054
4055         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4056         if (!NT_STATUS_IS_OK(status)) {
4057                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4058                           nt_errstr(status));
4059                 return false;
4060         }
4061
4062         ret = cli_bad_session_request(fd, &calling, &called);
4063         close(fd);
4064         if (!ret) {
4065                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4066                           nt_errstr(status));
4067                 return false;
4068         }
4069
4070         printf("finished bad nbt session test\n");
4071         return true;
4072 }
4073
4074 /* send random IPC commands */
4075 static bool run_randomipc(int dummy)
4076 {
4077         char *rparam = NULL;
4078         char *rdata = NULL;
4079         unsigned int rdrcnt,rprcnt;
4080         char param[1024];
4081         int api, param_len, i;
4082         struct cli_state *cli;
4083         bool correct = True;
4084         int count = 50000;
4085
4086         printf("starting random ipc test\n");
4087
4088         if (!torture_open_connection(&cli, 0)) {
4089                 return False;
4090         }
4091
4092         for (i=0;i<count;i++) {
4093                 api = sys_random() % 500;
4094                 param_len = (sys_random() % 64);
4095
4096                 rand_buf(param, param_len);
4097
4098                 SSVAL(param,0,api);
4099
4100                 cli_api(cli,
4101                         param, param_len, 8,
4102                         NULL, 0, CLI_BUFFER_SIZE,
4103                         &rparam, &rprcnt,
4104                         &rdata, &rdrcnt);
4105                 if (i % 100 == 0) {
4106                         printf("%d/%d\r", i,count);
4107                 }
4108         }
4109         printf("%d/%d\n", i, count);
4110
4111         if (!torture_close_connection(cli)) {
4112                 correct = False;
4113         }
4114
4115         SAFE_FREE(rparam);
4116         SAFE_FREE(rdata);
4117
4118         printf("finished random ipc test\n");
4119
4120         return correct;
4121 }
4122
4123
4124
4125 static void browse_callback(const char *sname, uint32_t stype,
4126                             const char *comment, void *state)
4127 {
4128         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4129 }
4130
4131
4132
4133 /*
4134   This test checks the browse list code
4135
4136 */
4137 static bool run_browsetest(int dummy)
4138 {
4139         static struct cli_state *cli;
4140         bool correct = True;
4141
4142         printf("starting browse test\n");
4143
4144         if (!torture_open_connection(&cli, 0)) {
4145                 return False;
4146         }
4147
4148         printf("domain list:\n");
4149         cli_NetServerEnum(cli, cli->server_domain,
4150                           SV_TYPE_DOMAIN_ENUM,
4151                           browse_callback, NULL);
4152
4153         printf("machine list:\n");
4154         cli_NetServerEnum(cli, cli->server_domain,
4155                           SV_TYPE_ALL,
4156                           browse_callback, NULL);
4157
4158         if (!torture_close_connection(cli)) {
4159                 correct = False;
4160         }
4161
4162         printf("browse test finished\n");
4163
4164         return correct;
4165
4166 }
4167
4168 static bool check_attributes(struct cli_state *cli,
4169                                 const char *fname,
4170                                 uint32_t expected_attrs)
4171 {
4172         uint32_t attrs = 0;
4173         NTSTATUS status = cli_getatr(cli,
4174                                 fname,
4175                                 &attrs,
4176                                 NULL,
4177                                 NULL);
4178         if (!NT_STATUS_IS_OK(status)) {
4179                 printf("cli_getatr failed with %s\n",
4180                         nt_errstr(status));
4181                 return false;
4182         }
4183         if (attrs != expected_attrs) {
4184                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4185                         (unsigned int)attrs,
4186                         (unsigned int)expected_attrs);
4187                 return false;
4188         }
4189         return true;
4190 }
4191
4192 /*
4193   This checks how the getatr calls works
4194 */
4195 static bool run_attrtest(int dummy)
4196 {
4197         struct cli_state *cli;
4198         uint16_t fnum;
4199         time_t t, t2;
4200         const char *fname = "\\attrib123456789.tst";
4201         bool correct = True;
4202         NTSTATUS status;
4203
4204         printf("starting attrib test\n");
4205
4206         if (!torture_open_connection(&cli, 0)) {
4207                 return False;
4208         }
4209
4210         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4211         status = cli_unlink(cli, fname, 0x20000);
4212         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4213                 correct = false;
4214                 goto out;
4215         }
4216
4217         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4218         cli_openx(cli, fname,
4219                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4220         cli_close(cli, fnum);
4221
4222         status = cli_getatr(cli, fname, NULL, NULL, &t);
4223         if (!NT_STATUS_IS_OK(status)) {
4224                 printf("getatr failed (%s)\n", nt_errstr(status));
4225                 correct = False;
4226         }
4227
4228         if (labs(t - time(NULL)) > 60*60*24*10) {
4229                 printf("ERROR: SMBgetatr bug. time is %s",
4230                        ctime(&t));
4231                 t = time(NULL);
4232                 correct = True;
4233         }
4234
4235         t2 = t-60*60*24; /* 1 day ago */
4236
4237         /* Ensure we can't set with out-of-range (unknown) attribute. */
4238         status = cli_setatr(cli, fname, 0x20000, t2);
4239         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4240                 correct = false;
4241                 goto out;
4242         }
4243
4244         status = cli_setatr(cli, fname, 0, t2);
4245         if (!NT_STATUS_IS_OK(status)) {
4246                 printf("setatr failed (%s)\n", nt_errstr(status));
4247                 correct = True;
4248         }
4249
4250         status = cli_getatr(cli, fname, NULL, NULL, &t);
4251         if (!NT_STATUS_IS_OK(status)) {
4252                 printf("getatr failed (%s)\n", nt_errstr(status));
4253                 correct = True;
4254         }
4255
4256         if (t != t2) {
4257                 printf("ERROR: getatr/setatr bug. times are\n%s",
4258                        ctime(&t));
4259                 printf("%s", ctime(&t2));
4260                 correct = True;
4261         }
4262
4263         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4264
4265         /* Check cli_setpathinfo_ext() */
4266         /* Re-create the file. */
4267         status = cli_openx(cli, fname,
4268                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 printf("Failed to recreate %s (%s)\n",
4271                         fname, nt_errstr(status));
4272                 correct = false;
4273         }
4274         cli_close(cli, fnum);
4275
4276         status = cli_setpathinfo_ext(
4277                 cli,
4278                 fname,
4279                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4280                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4281                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4282                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4283                 FILE_ATTRIBUTE_SYSTEM |
4284                 FILE_ATTRIBUTE_HIDDEN |
4285                 FILE_ATTRIBUTE_READONLY);
4286         if (!NT_STATUS_IS_OK(status)) {
4287                 printf("cli_setpathinfo_ext failed with %s\n",
4288                         nt_errstr(status));
4289                 correct = false;
4290         }
4291
4292         /* Check attributes are correct. */
4293         correct = check_attributes(cli,
4294                         fname,
4295                         FILE_ATTRIBUTE_SYSTEM |
4296                         FILE_ATTRIBUTE_HIDDEN |
4297                         FILE_ATTRIBUTE_READONLY);
4298         if (correct == false) {
4299                 goto out;
4300         }
4301
4302         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4303         status = cli_setpathinfo_ext(
4304                 cli,
4305                 fname,
4306                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4307                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4308                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4309                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4310                 FILE_ATTRIBUTE_NORMAL);
4311         if (!NT_STATUS_IS_OK(status)) {
4312                 printf("cli_setpathinfo_ext failed with %s\n",
4313                         nt_errstr(status));
4314                 correct = false;
4315         }
4316
4317         /* Check attributes are correct. */
4318         correct = check_attributes(cli,
4319                         fname,
4320                         FILE_ATTRIBUTE_SYSTEM |
4321                         FILE_ATTRIBUTE_HIDDEN |
4322                         FILE_ATTRIBUTE_READONLY);
4323         if (correct == false) {
4324                 goto out;
4325         }
4326
4327         /* Setting to (uint16_t)-1 should also be ignored. */
4328         status = cli_setpathinfo_ext(
4329                 cli,
4330                 fname,
4331                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4332                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4333                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4334                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4335                 (uint32_t)-1);
4336         if (!NT_STATUS_IS_OK(status)) {
4337                 printf("cli_setpathinfo_ext failed with %s\n",
4338                         nt_errstr(status));
4339                 correct = false;
4340         }
4341
4342         /* Check attributes are correct. */
4343         correct = check_attributes(cli,
4344                         fname,
4345                         FILE_ATTRIBUTE_SYSTEM |
4346                         FILE_ATTRIBUTE_HIDDEN |
4347                         FILE_ATTRIBUTE_READONLY);
4348         if (correct == false) {
4349                 goto out;
4350         }
4351
4352         /* Setting to 0 should clear them all. */
4353         status = cli_setpathinfo_ext(
4354                 cli,
4355                 fname,
4356                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4357                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4358                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4359                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4360                 0);
4361         if (!NT_STATUS_IS_OK(status)) {
4362                 printf("cli_setpathinfo_ext failed with %s\n",
4363                         nt_errstr(status));
4364                 correct = false;
4365         }
4366
4367         /* Check attributes are correct. */
4368         correct = check_attributes(cli,
4369                         fname,
4370                         FILE_ATTRIBUTE_NORMAL);
4371         if (correct == false) {
4372                 goto out;
4373         }
4374
4375   out:
4376
4377         cli_unlink(cli,
4378                 fname,
4379                 FILE_ATTRIBUTE_SYSTEM |
4380                 FILE_ATTRIBUTE_HIDDEN|
4381                 FILE_ATTRIBUTE_READONLY);
4382
4383         if (!torture_close_connection(cli)) {
4384                 correct = False;
4385         }
4386
4387         printf("attrib test finished\n");
4388
4389         return correct;
4390 }
4391
4392 static NTSTATUS cli_qfilename(
4393         struct cli_state *cli,
4394         uint16_t fnum,
4395         TALLOC_CTX *mem_ctx,
4396         char **_name)
4397 {
4398         uint16_t recv_flags2;
4399         uint8_t *rdata;
4400         uint32_t num_rdata;
4401         NTSTATUS status;
4402         char *name = NULL;
4403         uint32_t namelen;
4404
4405         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4406                                SMB_QUERY_FILE_NAME_INFO,
4407                                4, CLI_BUFFER_SIZE, &recv_flags2,
4408                                &rdata, &num_rdata);
4409         if (!NT_STATUS_IS_OK(status)) {
4410                 return status;
4411         }
4412
4413         namelen = IVAL(rdata, 0);
4414         if (namelen > (num_rdata - 4)) {
4415                 TALLOC_FREE(rdata);
4416                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4417         }
4418
4419         pull_string_talloc(mem_ctx,
4420                            (const char *)rdata,
4421                            recv_flags2,
4422                            &name,
4423                            rdata + 4,
4424                            namelen,
4425                            STR_UNICODE);
4426         if (name == NULL) {
4427                 status = map_nt_error_from_unix(errno);
4428                 TALLOC_FREE(rdata);
4429                 return status;
4430         }
4431
4432         *_name = name;
4433         TALLOC_FREE(rdata);
4434         return NT_STATUS_OK;
4435 }
4436
4437 /*
4438   This checks a couple of trans2 calls
4439 */
4440 static bool run_trans2test(int dummy)
4441 {
4442         struct cli_state *cli;
4443         uint16_t fnum;
4444         off_t size;
4445         time_t c_time, a_time, m_time;
4446         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4447         const char *fname = "\\trans2.tst";
4448         const char *dname = "\\trans2";
4449         const char *fname2 = "\\trans2\\trans2.tst";
4450         char *pname = NULL;
4451         bool correct = True;
4452         NTSTATUS status;
4453         uint32_t fs_attr;
4454         uint64_t ino;
4455
4456         printf("starting trans2 test\n");
4457
4458         if (!torture_open_connection(&cli, 0)) {
4459                 return False;
4460         }
4461
4462         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4463                 /* Ensure ino is zero, SMB2 gets a real one. */
4464                 ino = 0;
4465         } else {
4466                 /* Ensure ino is -1, SMB1 never gets a real one. */
4467                 ino = (uint64_t)-1;
4468         }
4469
4470         status = cli_get_fs_attr_info(cli, &fs_attr);
4471         if (!NT_STATUS_IS_OK(status)) {
4472                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4473                        nt_errstr(status));
4474                 correct = false;
4475         }
4476
4477         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4478         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4479         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4480                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4481         if (!NT_STATUS_IS_OK(status)) {
4482                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4483                 correct = False;
4484         }
4485
4486         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4487         if (!NT_STATUS_IS_OK(status)) {
4488                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4489                 correct = False;
4490         }
4491         else if (strcmp(pname, fname)) {
4492                 printf("qfilename gave different name? [%s] [%s]\n",
4493                        fname, pname);
4494                 correct = False;
4495         }
4496
4497         cli_close(cli, fnum);
4498
4499         sleep(2);
4500
4501         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4502         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4503                           &fnum);
4504         if (!NT_STATUS_IS_OK(status)) {
4505                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4506                 return False;
4507         }
4508         cli_close(cli, fnum);
4509
4510         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4511                                 NULL);
4512         if (!NT_STATUS_IS_OK(status)) {
4513                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4514                 correct = False;
4515         } else {
4516                 time_t t = time(NULL);
4517
4518                 if (c_time != m_time) {
4519                         printf("create time=%s", ctime(&c_time));
4520                         printf("modify time=%s", ctime(&m_time));
4521                         printf("This system appears to have sticky create times\n");
4522                 }
4523                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4524                         printf("access time=%s", ctime(&a_time));
4525                         printf("This system appears to set a midnight access time\n");
4526                         correct = False;
4527                 }
4528
4529                 if (labs(m_time - t) > 60*60*24*7) {
4530                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4531                         correct = False;
4532                 }
4533         }
4534
4535
4536         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4537         cli_openx(cli, fname,
4538                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4539         cli_close(cli, fnum);
4540         status = cli_qpathinfo2(cli,
4541                                 fname,
4542                                 &c_time_ts,
4543                                 &a_time_ts,
4544                                 &w_time_ts,
4545                                 &m_time_ts,
4546                                 &size,
4547                                 NULL,
4548                                 &ino,
4549                                 NULL);
4550         if (!NT_STATUS_IS_OK(status)) {
4551                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4552                 correct = False;
4553         } else {
4554                 if (w_time_ts.tv_sec < 60*60*24*2) {
4555                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4556                         printf("This system appears to set a initial 0 write time\n");
4557                         correct = False;
4558                 }
4559                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4560                         /* SMB2 should always return an inode. */
4561                         if (ino == 0) {
4562                                 printf("SMB2 bad inode (0)\n");
4563                                 correct = false;
4564                         }
4565                 } else {
4566                         /* SMB1 must always return zero here. */
4567                         if (ino != 0) {
4568                                 printf("SMB1 bad inode (!0)\n");
4569                                 correct = false;
4570                         }
4571                 }
4572         }
4573
4574         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4575
4576
4577         /* check if the server updates the directory modification time
4578            when creating a new file */
4579         status = cli_mkdir(cli, dname);
4580         if (!NT_STATUS_IS_OK(status)) {
4581                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4582                 correct = False;
4583         }
4584         sleep(3);
4585         status = cli_qpathinfo2(cli,
4586                                 "\\trans2\\",
4587                                 &c_time_ts,
4588                                 &a_time_ts,
4589                                 &w_time_ts,
4590                                 &m_time_ts,
4591                                 &size,
4592                                 NULL,
4593                                 NULL,
4594                                 NULL);
4595         if (!NT_STATUS_IS_OK(status)) {
4596                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4597                 correct = False;
4598         }
4599
4600         cli_openx(cli, fname2,
4601                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4602         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4603         cli_close(cli, fnum);
4604         status = cli_qpathinfo2(cli,
4605                                 "\\trans2\\",
4606                                 &c_time_ts,
4607                                 &a_time_ts,
4608                                 &w_time_ts,
4609                                 &m_time2_ts,
4610                                 &size,
4611                                 NULL,
4612                                 NULL,
4613                                 NULL);
4614         if (!NT_STATUS_IS_OK(status)) {
4615                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4616                 correct = False;
4617         } else {
4618                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4619                     == 0) {
4620                         printf("This system does not update directory modification times\n");
4621                         correct = False;
4622                 }
4623         }
4624         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4625         cli_rmdir(cli, dname);
4626
4627         if (!torture_close_connection(cli)) {
4628                 correct = False;
4629         }
4630
4631         printf("trans2 test finished\n");
4632
4633         return correct;
4634 }
4635
4636 /*
4637   This checks new W2K calls.
4638 */
4639
4640 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4641 {
4642         uint8_t *buf = NULL;
4643         uint32_t len;
4644         NTSTATUS status;
4645
4646         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4647                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4648         if (!NT_STATUS_IS_OK(status)) {
4649                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4650                        nt_errstr(status));
4651         } else {
4652                 printf("qfileinfo: level %d, len = %u\n", level, len);
4653                 dump_data(0, (uint8_t *)buf, len);
4654                 printf("\n");
4655         }
4656         TALLOC_FREE(buf);
4657         return status;
4658 }
4659
4660 static bool run_w2ktest(int dummy)
4661 {
4662         struct cli_state *cli;
4663         uint16_t fnum;
4664         const char *fname = "\\w2ktest\\w2k.tst";
4665         int level;
4666         bool correct = True;
4667
4668         printf("starting w2k test\n");
4669
4670         if (!torture_open_connection(&cli, 0)) {
4671                 return False;
4672         }
4673
4674         cli_openx(cli, fname,
4675                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4676
4677         for (level = 1004; level < 1040; level++) {
4678                 new_trans(cli, fnum, level);
4679         }
4680
4681         cli_close(cli, fnum);
4682
4683         if (!torture_close_connection(cli)) {
4684                 correct = False;
4685         }
4686
4687         printf("w2k test finished\n");
4688
4689         return correct;
4690 }
4691
4692
4693 /*
4694   this is a harness for some oplock tests
4695  */
4696 static bool run_oplock1(int dummy)
4697 {
4698         struct cli_state *cli1;
4699         const char *fname = "\\lockt1.lck";
4700         uint16_t fnum1;
4701         bool correct = True;
4702         NTSTATUS status;
4703
4704         printf("starting oplock test 1\n");
4705
4706         if (!torture_open_connection(&cli1, 0)) {
4707                 return False;
4708         }
4709
4710         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4711
4712         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4713
4714         cli1->use_oplocks = True;
4715
4716         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4717                           &fnum1);
4718         if (!NT_STATUS_IS_OK(status)) {
4719                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4720                 return False;
4721         }
4722
4723         cli1->use_oplocks = False;
4724
4725         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4727
4728         status = cli_close(cli1, fnum1);
4729         if (!NT_STATUS_IS_OK(status)) {
4730                 printf("close2 failed (%s)\n", nt_errstr(status));
4731                 return False;
4732         }
4733
4734         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4735         if (!NT_STATUS_IS_OK(status)) {
4736                 printf("unlink failed (%s)\n", nt_errstr(status));
4737                 return False;
4738         }
4739
4740         if (!torture_close_connection(cli1)) {
4741                 correct = False;
4742         }
4743
4744         printf("finished oplock test 1\n");
4745
4746         return correct;
4747 }
4748
4749 static bool run_oplock2(int dummy)
4750 {
4751         struct cli_state *cli1, *cli2;
4752         const char *fname = "\\lockt2.lck";
4753         uint16_t fnum1, fnum2;
4754         int saved_use_oplocks = use_oplocks;
4755         char buf[4];
4756         bool correct = True;
4757         volatile bool *shared_correct;
4758         size_t nread;
4759         NTSTATUS status;
4760
4761         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4762         *shared_correct = True;
4763
4764         use_level_II_oplocks = True;
4765         use_oplocks = True;
4766
4767         printf("starting oplock test 2\n");
4768
4769         if (!torture_open_connection(&cli1, 0)) {
4770                 use_level_II_oplocks = False;
4771                 use_oplocks = saved_use_oplocks;
4772                 return False;
4773         }
4774
4775         if (!torture_open_connection(&cli2, 1)) {
4776                 use_level_II_oplocks = False;
4777                 use_oplocks = saved_use_oplocks;
4778                 return False;
4779         }
4780
4781         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4782
4783         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4784         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4785
4786         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4787                           &fnum1);
4788         if (!NT_STATUS_IS_OK(status)) {
4789                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4790                 return False;
4791         }
4792
4793         /* Don't need the globals any more. */
4794         use_level_II_oplocks = False;
4795         use_oplocks = saved_use_oplocks;
4796
4797         if (fork() == 0) {
4798                 /* Child code */
4799                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4800                 if (!NT_STATUS_IS_OK(status)) {
4801                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4802                         *shared_correct = False;
4803                         exit(0);
4804                 }
4805
4806                 sleep(2);
4807
4808                 status = cli_close(cli2, fnum2);
4809                 if (!NT_STATUS_IS_OK(status)) {
4810                         printf("close2 failed (%s)\n", nt_errstr(status));
4811                         *shared_correct = False;
4812                 }
4813
4814                 exit(0);
4815         }
4816
4817         sleep(2);
4818
4819         /* Ensure cli1 processes the break. Empty file should always return 0
4820          * bytes.  */
4821         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4822         if (!NT_STATUS_IS_OK(status)) {
4823                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4824                 correct = false;
4825         } else if (nread != 0) {
4826                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4827                       (unsigned long)nread, 0);
4828                 correct = false;
4829         }
4830
4831         /* Should now be at level II. */
4832         /* Test if sending a write locks causes a break to none. */
4833         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4834         if (!NT_STATUS_IS_OK(status)) {
4835                 printf("lock failed (%s)\n", nt_errstr(status));
4836                 correct = False;
4837         }
4838
4839         cli_unlock(cli1, fnum1, 0, 4);
4840
4841         sleep(2);
4842
4843         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4844         if (!NT_STATUS_IS_OK(status)) {
4845                 printf("lock failed (%s)\n", nt_errstr(status));
4846                 correct = False;
4847         }
4848
4849         cli_unlock(cli1, fnum1, 0, 4);
4850
4851         sleep(2);
4852
4853         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4854
4855         status = cli_close(cli1, fnum1);
4856         if (!NT_STATUS_IS_OK(status)) {
4857                 printf("close1 failed (%s)\n", nt_errstr(status));
4858                 correct = False;
4859         }
4860
4861         sleep(4);
4862
4863         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4864         if (!NT_STATUS_IS_OK(status)) {
4865                 printf("unlink failed (%s)\n", nt_errstr(status));
4866                 correct = False;
4867         }
4868
4869         if (!torture_close_connection(cli1)) {
4870                 correct = False;
4871         }
4872
4873         if (!*shared_correct) {
4874                 correct = False;
4875         }
4876
4877         printf("finished oplock test 2\n");
4878
4879         return correct;
4880 }
4881
4882 struct oplock4_state {
4883         struct tevent_context *ev;
4884         struct cli_state *cli;
4885         bool *got_break;
4886         uint16_t *fnum2;
4887 };
4888
4889 static void oplock4_got_break(struct tevent_req *req);
4890 static void oplock4_got_open(struct tevent_req *req);
4891
4892 static bool run_oplock4(int dummy)
4893 {
4894         struct tevent_context *ev;
4895         struct cli_state *cli1, *cli2;
4896         struct tevent_req *oplock_req, *open_req;
4897         const char *fname = "\\lockt4.lck";
4898         const char *fname_ln = "\\lockt4_ln.lck";
4899         uint16_t fnum1, fnum2;
4900         int saved_use_oplocks = use_oplocks;
4901         NTSTATUS status;
4902         bool correct = true;
4903
4904         bool got_break;
4905
4906         struct oplock4_state *state;
4907
4908         printf("starting oplock test 4\n");
4909
4910         if (!torture_open_connection(&cli1, 0)) {
4911                 use_level_II_oplocks = false;
4912                 use_oplocks = saved_use_oplocks;
4913                 return false;
4914         }
4915
4916         if (!torture_open_connection(&cli2, 1)) {
4917                 use_level_II_oplocks = false;
4918                 use_oplocks = saved_use_oplocks;
4919                 return false;
4920         }
4921
4922         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4923         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4924
4925         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4926         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4927
4928         /* Create the file. */
4929         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4930                           &fnum1);
4931         if (!NT_STATUS_IS_OK(status)) {
4932                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4933                 return false;
4934         }
4935
4936         status = cli_close(cli1, fnum1);
4937         if (!NT_STATUS_IS_OK(status)) {
4938                 printf("close1 failed (%s)\n", nt_errstr(status));
4939                 return false;
4940         }
4941
4942         /* Now create a hardlink. */
4943         status = cli_hardlink(cli1, fname, fname_ln);
4944         if (!NT_STATUS_IS_OK(status)) {
4945                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4946                 return false;
4947         }
4948
4949         /* Prove that opening hardlinks cause deny modes to conflict. */
4950         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4951         if (!NT_STATUS_IS_OK(status)) {
4952                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4953                 return false;
4954         }
4955
4956         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4957         if (NT_STATUS_IS_OK(status)) {
4958                 printf("open of %s succeeded - should fail with sharing violation.\n",
4959                         fname_ln);
4960                 return false;
4961         }
4962
4963         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4964                 printf("open of %s should fail with sharing violation. Got %s\n",
4965                         fname_ln, nt_errstr(status));
4966                 return false;
4967         }
4968
4969         status = cli_close(cli1, fnum1);
4970         if (!NT_STATUS_IS_OK(status)) {
4971                 printf("close1 failed (%s)\n", nt_errstr(status));
4972                 return false;
4973         }
4974
4975         cli1->use_oplocks = true;
4976         cli2->use_oplocks = true;
4977
4978         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4979         if (!NT_STATUS_IS_OK(status)) {
4980                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4981                 return false;
4982         }
4983
4984         ev = samba_tevent_context_init(talloc_tos());
4985         if (ev == NULL) {
4986                 printf("tevent_context_init failed\n");
4987                 return false;
4988         }
4989
4990         state = talloc(ev, struct oplock4_state);
4991         if (state == NULL) {
4992                 printf("talloc failed\n");
4993                 return false;
4994         }
4995         state->ev = ev;
4996         state->cli = cli1;
4997         state->got_break = &got_break;
4998         state->fnum2 = &fnum2;
4999
5000         oplock_req = cli_smb_oplock_break_waiter_send(
5001                 talloc_tos(), ev, cli1);
5002         if (oplock_req == NULL) {
5003                 printf("cli_smb_oplock_break_waiter_send failed\n");
5004                 return false;
5005         }
5006         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5007
5008         open_req = cli_openx_send(
5009                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5010         if (open_req == NULL) {
5011                 printf("cli_openx_send failed\n");
5012                 return false;
5013         }
5014         tevent_req_set_callback(open_req, oplock4_got_open, state);
5015
5016         got_break = false;
5017         fnum2 = 0xffff;
5018
5019         while (!got_break || fnum2 == 0xffff) {
5020                 int ret;
5021                 ret = tevent_loop_once(ev);
5022                 if (ret == -1) {
5023                         printf("tevent_loop_once failed: %s\n",
5024                                strerror(errno));
5025                         return false;
5026                 }
5027         }
5028
5029         status = cli_close(cli2, fnum2);
5030         if (!NT_STATUS_IS_OK(status)) {
5031                 printf("close2 failed (%s)\n", nt_errstr(status));
5032                 correct = false;
5033         }
5034
5035         status = cli_close(cli1, fnum1);
5036         if (!NT_STATUS_IS_OK(status)) {
5037                 printf("close1 failed (%s)\n", nt_errstr(status));
5038                 correct = false;
5039         }
5040
5041         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5042         if (!NT_STATUS_IS_OK(status)) {
5043                 printf("unlink failed (%s)\n", nt_errstr(status));
5044                 correct = false;
5045         }
5046
5047         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5048         if (!NT_STATUS_IS_OK(status)) {
5049                 printf("unlink failed (%s)\n", nt_errstr(status));
5050                 correct = false;
5051         }
5052
5053         if (!torture_close_connection(cli1)) {
5054                 correct = false;
5055         }
5056
5057         if (!got_break) {
5058                 correct = false;
5059         }
5060
5061         printf("finished oplock test 4\n");
5062
5063         return correct;
5064 }
5065
5066 static void oplock4_got_break(struct tevent_req *req)
5067 {
5068         struct oplock4_state *state = tevent_req_callback_data(
5069                 req, struct oplock4_state);
5070         uint16_t fnum;
5071         uint8_t level;
5072         NTSTATUS status;
5073
5074         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5075         TALLOC_FREE(req);
5076         if (!NT_STATUS_IS_OK(status)) {
5077                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5078                        nt_errstr(status));
5079                 return;
5080         }
5081         *state->got_break = true;
5082
5083         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5084                                   NO_OPLOCK);
5085         if (req == NULL) {
5086                 printf("cli_oplock_ack_send failed\n");
5087                 return;
5088         }
5089 }
5090
5091 static void oplock4_got_open(struct tevent_req *req)
5092 {
5093         struct oplock4_state *state = tevent_req_callback_data(
5094                 req, struct oplock4_state);
5095         NTSTATUS status;
5096
5097         status = cli_openx_recv(req, state->fnum2);
5098         if (!NT_STATUS_IS_OK(status)) {
5099                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5100                 *state->fnum2 = 0xffff;
5101         }
5102 }
5103
5104 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5105
5106 struct oplock5_state {
5107         int pipe_down_fd;
5108 };
5109
5110 /*
5111  * Async open the file that has a kernel oplock, do an echo to get
5112  * that 100% across, close the file to signal to the child fd that the
5113  * oplock can be dropped, wait for the open reply.
5114  */
5115
5116 static void oplock5_opened(struct tevent_req *subreq);
5117 static void oplock5_pong(struct tevent_req *subreq);
5118 static void oplock5_timedout(struct tevent_req *subreq);
5119
5120 static struct tevent_req *oplock5_send(
5121         TALLOC_CTX *mem_ctx,
5122         struct tevent_context *ev,
5123         struct cli_state *cli,
5124         const char *fname,
5125         int pipe_down_fd)
5126 {
5127         struct tevent_req *req = NULL, *subreq = NULL;
5128         struct oplock5_state *state = NULL;
5129         static uint8_t data = 0;
5130
5131         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5132         if (req == NULL) {
5133                 return NULL;
5134         }
5135         state->pipe_down_fd = pipe_down_fd;
5136
5137         subreq = cli_ntcreate_send(
5138                 state,
5139                 ev,
5140                 cli,
5141                 fname,
5142                 0,                      /* CreatFlags */
5143                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5144                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5145                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5146                 FILE_OPEN,               /* CreateDisposition */
5147                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5148                 0,                       /* Impersonation */
5149                 0);                      /* SecurityFlags */
5150         if (tevent_req_nomem(subreq, req)) {
5151                 return tevent_req_post(req, ev);
5152         }
5153         tevent_req_set_callback(subreq, oplock5_opened, req);
5154
5155         subreq = cli_echo_send(
5156                 state,
5157                 ev,
5158                 cli,
5159                 1,
5160                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5161         if (tevent_req_nomem(subreq, req)) {
5162                 return tevent_req_post(req, ev);
5163         }
5164         tevent_req_set_callback(subreq, oplock5_pong, req);
5165
5166         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5167         if (tevent_req_nomem(subreq, req)) {
5168                 return tevent_req_post(req, ev);
5169         }
5170         tevent_req_set_callback(subreq, oplock5_timedout, req);
5171
5172         return req;
5173 }
5174
5175 static void oplock5_opened(struct tevent_req *subreq)
5176 {
5177         struct tevent_req *req = tevent_req_callback_data(
5178                 subreq, struct tevent_req);
5179         NTSTATUS status;
5180         uint16_t fnum;
5181
5182         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5183         TALLOC_FREE(subreq);
5184         if (tevent_req_nterror(req, status)) {
5185                 return;
5186         }
5187         tevent_req_done(req);
5188 }
5189
5190 static void oplock5_pong(struct tevent_req *subreq)
5191 {
5192         struct tevent_req *req = tevent_req_callback_data(
5193                 subreq, struct tevent_req);
5194         struct oplock5_state *state = tevent_req_data(
5195                 req, struct oplock5_state);
5196         NTSTATUS status;
5197
5198         status = cli_echo_recv(subreq);
5199         TALLOC_FREE(subreq);
5200         if (tevent_req_nterror(req, status)) {
5201                 return;
5202         }
5203
5204         close(state->pipe_down_fd);
5205 }
5206
5207 static void oplock5_timedout(struct tevent_req *subreq)
5208 {
5209         struct tevent_req *req = tevent_req_callback_data(
5210                 subreq, struct tevent_req);
5211         bool ok;
5212
5213         ok = tevent_wakeup_recv(subreq);
5214         TALLOC_FREE(subreq);
5215         if (!ok) {
5216                 tevent_req_oom(req);
5217                 return;
5218         }
5219         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5220 }
5221
5222 static NTSTATUS oplock5_recv(struct tevent_req *req)
5223 {
5224         return tevent_req_simple_recv_ntstatus(req);
5225 }
5226
5227 static bool run_oplock5(int dummy)
5228 {
5229         struct tevent_context *ev = NULL;
5230         struct tevent_req *req = NULL;
5231         struct cli_state *cli = NULL;
5232         const char *fname = "oplock5.txt";
5233         int pipe_down[2], pipe_up[2];
5234         pid_t child_pid;
5235         uint8_t c = '\0';
5236         NTSTATUS status;
5237         int ret;
5238         bool ok;
5239
5240         printf("starting oplock5\n");
5241
5242         if (local_path == NULL) {
5243                 d_fprintf(stderr, "oplock5 must be given a local path via "
5244                           "-l <localpath>\n");
5245                 return false;
5246         }
5247
5248         ret = pipe(pipe_down);
5249         if (ret == -1) {
5250                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5251                 return false;
5252         }
5253         ret = pipe(pipe_up);
5254         if (ret == -1) {
5255                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5256                 return false;
5257         }
5258
5259         child_pid = fork();
5260         if (child_pid == -1) {
5261                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5262                 return false;
5263         }
5264
5265         if (child_pid == 0) {
5266                 char *local_file = NULL;
5267                 int fd;
5268
5269                 close(pipe_down[1]);
5270                 close(pipe_up[0]);
5271
5272                 local_file = talloc_asprintf(
5273                         talloc_tos(), "%s/%s", local_path, fname);
5274                 if (local_file == 0) {
5275                         c = 1;
5276                         goto do_write;
5277                 }
5278                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5279                 if (fd == -1) {
5280                         d_fprintf(stderr,
5281                                   "open(%s) in child failed: %s\n",
5282                                   local_file,
5283                                   strerror(errno));
5284                         c = 2;
5285                         goto do_write;
5286                 }
5287
5288                 signal(SIGIO, SIG_IGN);
5289
5290                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5291                 if (ret == -1) {
5292                         d_fprintf(stderr,
5293                                   "SETLEASE in child failed: %s\n",
5294                                   strerror(errno));
5295                         c = 3;
5296                         goto do_write;
5297                 }
5298
5299         do_write:
5300                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5301                 if (ret == -1) {
5302                         d_fprintf(stderr,
5303                                   "sys_write failed: %s\n",
5304                                   strerror(errno));
5305                         exit(4);
5306                 }
5307                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5308                 if (ret == -1) {
5309                         d_fprintf(stderr,
5310                                   "sys_read failed: %s\n",
5311                                   strerror(errno));
5312                         exit(5);
5313                 }
5314                 exit(0);
5315         }
5316
5317         close(pipe_up[1]);
5318         close(pipe_down[0]);
5319
5320         ret = sys_read(pipe_up[0], &c, sizeof(c));
5321         if (ret != 1) {
5322                 d_fprintf(stderr,
5323                           "sys_read failed: %s\n",
5324                           strerror(errno));
5325                 return false;
5326         }
5327         if (c != 0) {
5328                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5329                 return false;
5330         }
5331
5332         ok = torture_open_connection(&cli, 0);
5333         if (!ok) {
5334                 d_fprintf(stderr, "torture_open_connection failed\n");
5335                 return false;
5336         }
5337
5338         ev = samba_tevent_context_init(talloc_tos());
5339         if (ev == NULL) {
5340                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5341                 return false;
5342         }
5343
5344         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5345         if (req == NULL) {
5346                 d_fprintf(stderr, "oplock5_send failed\n");
5347                 return false;
5348         }
5349
5350         ok = tevent_req_poll_ntstatus(req, ev, &status);
5351         if (!ok) {
5352                 d_fprintf(stderr,
5353                           "tevent_req_poll_ntstatus failed: %s\n",
5354                           nt_errstr(status));
5355                 return false;
5356         }
5357
5358         status = oplock5_recv(req);
5359         TALLOC_FREE(req);
5360         if (!NT_STATUS_IS_OK(status)) {
5361                 d_fprintf(stderr,
5362                           "oplock5 failed: %s\n",
5363                           nt_errstr(status));
5364                 return false;
5365         }
5366
5367         return true;
5368 }
5369
5370 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5371
5372 /*
5373   Test delete on close semantics.
5374  */
5375 static bool run_deletetest(int dummy)
5376 {
5377         struct cli_state *cli1 = NULL;
5378         struct cli_state *cli2 = NULL;
5379         const char *fname = "\\delete.file";
5380         uint16_t fnum1 = (uint16_t)-1;
5381         uint16_t fnum2 = (uint16_t)-1;
5382         bool correct = false;
5383         NTSTATUS status;
5384
5385         printf("starting delete test\n");
5386
5387         if (!torture_open_connection(&cli1, 0)) {
5388                 return False;
5389         }
5390
5391         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5392
5393         /* Test 1 - this should delete the file on close. */
5394
5395         cli_setatr(cli1, fname, 0, 0);
5396         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5397
5398         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5399                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5400                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5401         if (!NT_STATUS_IS_OK(status)) {
5402                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5403                 goto fail;
5404         }
5405
5406         status = cli_close(cli1, fnum1);
5407         if (!NT_STATUS_IS_OK(status)) {
5408                 printf("[1] close failed (%s)\n", nt_errstr(status));
5409                 goto fail;
5410         }
5411
5412         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5413         if (NT_STATUS_IS_OK(status)) {
5414                 printf("[1] open of %s succeeded (should fail)\n", fname);
5415                 goto fail;
5416         }
5417
5418         printf("first delete on close test succeeded.\n");
5419
5420         /* Test 2 - this should delete the file on close. */
5421
5422         cli_setatr(cli1, fname, 0, 0);
5423         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5424
5425         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5426                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5427                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5428         if (!NT_STATUS_IS_OK(status)) {
5429                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5430                 goto fail;
5431         }
5432
5433         status = cli_nt_delete_on_close(cli1, fnum1, true);
5434         if (!NT_STATUS_IS_OK(status)) {
5435                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5436                 goto fail;
5437         }
5438
5439         status = cli_close(cli1, fnum1);
5440         if (!NT_STATUS_IS_OK(status)) {
5441                 printf("[2] close failed (%s)\n", nt_errstr(status));
5442                 goto fail;
5443         }
5444
5445         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5446         if (NT_STATUS_IS_OK(status)) {
5447                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5448                 status = cli_close(cli1, fnum1);
5449                 if (!NT_STATUS_IS_OK(status)) {
5450                         printf("[2] close failed (%s)\n", nt_errstr(status));
5451                 }
5452                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5453                 goto fail;
5454         }
5455
5456         printf("second delete on close test succeeded.\n");
5457
5458         /* Test 3 - ... */
5459         cli_setatr(cli1, fname, 0, 0);
5460         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5461
5462         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5463                               FILE_ATTRIBUTE_NORMAL,
5464                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5465                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5466         if (!NT_STATUS_IS_OK(status)) {
5467                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5468                 goto fail;
5469         }
5470
5471         /* This should fail with a sharing violation - open for delete is only compatible
5472            with SHARE_DELETE. */
5473
5474         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5475                               FILE_ATTRIBUTE_NORMAL,
5476                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5477                               FILE_OPEN, 0, 0, &fnum2, NULL);
5478         if (NT_STATUS_IS_OK(status)) {
5479                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5480                 goto fail;
5481         }
5482
5483         /* This should succeed. */
5484         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5485                              FILE_ATTRIBUTE_NORMAL,
5486                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5487                              FILE_OPEN, 0, 0, &fnum2, NULL);
5488         if (!NT_STATUS_IS_OK(status)) {
5489                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5490                 goto fail;
5491         }
5492
5493         status = cli_nt_delete_on_close(cli1, fnum1, true);
5494         if (!NT_STATUS_IS_OK(status)) {
5495                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5496                 goto fail;
5497         }
5498
5499         status = cli_close(cli1, fnum1);
5500         if (!NT_STATUS_IS_OK(status)) {
5501                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5502                 goto fail;
5503         }
5504
5505         status = cli_close(cli1, fnum2);
5506         if (!NT_STATUS_IS_OK(status)) {
5507                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5508                 goto fail;
5509         }
5510
5511         /* This should fail - file should no longer be there. */
5512
5513         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5514         if (NT_STATUS_IS_OK(status)) {
5515                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5516                 status = cli_close(cli1, fnum1);
5517                 if (!NT_STATUS_IS_OK(status)) {
5518                         printf("[3] close failed (%s)\n", nt_errstr(status));
5519                 }
5520                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5521                 goto fail;
5522         }
5523
5524         printf("third delete on close test succeeded.\n");
5525
5526         /* Test 4 ... */
5527         cli_setatr(cli1, fname, 0, 0);
5528         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5529
5530         status = cli_ntcreate(cli1, fname, 0,
5531                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5532                               FILE_ATTRIBUTE_NORMAL,
5533                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5534                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5535         if (!NT_STATUS_IS_OK(status)) {
5536                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5537                 goto fail;
5538         }
5539
5540         /* This should succeed. */
5541         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5542                              FILE_ATTRIBUTE_NORMAL,
5543                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5544                              FILE_OPEN, 0, 0, &fnum2, NULL);
5545         if (!NT_STATUS_IS_OK(status)) {
5546                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5547                 goto fail;
5548         }
5549
5550         status = cli_close(cli1, fnum2);
5551         if (!NT_STATUS_IS_OK(status)) {
5552                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5553                 goto fail;
5554         }
5555
5556         status = cli_nt_delete_on_close(cli1, fnum1, true);
5557         if (!NT_STATUS_IS_OK(status)) {
5558                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5559                 goto fail;
5560         }
5561
5562         /* This should fail - no more opens once delete on close set. */
5563         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5564                               FILE_ATTRIBUTE_NORMAL,
5565                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5566                               FILE_OPEN, 0, 0, &fnum2, NULL);
5567         if (NT_STATUS_IS_OK(status)) {
5568                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5569                 goto fail;
5570         }
5571
5572         status = cli_close(cli1, fnum1);
5573         if (!NT_STATUS_IS_OK(status)) {
5574                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5575                 goto fail;
5576         }
5577
5578         printf("fourth delete on close test succeeded.\n");
5579
5580         /* Test 5 ... */
5581         cli_setatr(cli1, fname, 0, 0);
5582         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5583
5584         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5585         if (!NT_STATUS_IS_OK(status)) {
5586                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5587                 goto fail;
5588         }
5589
5590         /* This should fail - only allowed on NT opens with DELETE access. */
5591
5592         status = cli_nt_delete_on_close(cli1, fnum1, true);
5593         if (NT_STATUS_IS_OK(status)) {
5594                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5595                 goto fail;
5596         }
5597
5598         status = cli_close(cli1, fnum1);
5599         if (!NT_STATUS_IS_OK(status)) {
5600                 printf("[5] close failed (%s)\n", nt_errstr(status));
5601                 goto fail;
5602         }
5603
5604         printf("fifth delete on close test succeeded.\n");
5605
5606         /* Test 6 ... */
5607         cli_setatr(cli1, fname, 0, 0);
5608         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5609
5610         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5611                              FILE_ATTRIBUTE_NORMAL,
5612                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5613                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5614         if (!NT_STATUS_IS_OK(status)) {
5615                 printf("[6] open of %s failed (%s)\n", fname,
5616                        nt_errstr(status));
5617                 goto fail;
5618         }
5619
5620         /* This should fail - only allowed on NT opens with DELETE access. */
5621
5622         status = cli_nt_delete_on_close(cli1, fnum1, true);
5623         if (NT_STATUS_IS_OK(status)) {
5624                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5625                 goto fail;
5626         }
5627
5628         status = cli_close(cli1, fnum1);
5629         if (!NT_STATUS_IS_OK(status)) {
5630                 printf("[6] close failed (%s)\n", nt_errstr(status));
5631                 goto fail;
5632         }
5633
5634         printf("sixth delete on close test succeeded.\n");
5635
5636         /* Test 7 ... */
5637         cli_setatr(cli1, fname, 0, 0);
5638         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5639
5640         status = cli_ntcreate(cli1, fname, 0,
5641                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5642                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5643                               0, 0, &fnum1, NULL);
5644         if (!NT_STATUS_IS_OK(status)) {
5645                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5646                 goto fail;
5647         }
5648
5649         status = cli_nt_delete_on_close(cli1, fnum1, true);
5650         if (!NT_STATUS_IS_OK(status)) {
5651                 printf("[7] setting delete_on_close on file failed !\n");
5652                 goto fail;
5653         }
5654
5655         status = cli_nt_delete_on_close(cli1, fnum1, false);
5656         if (!NT_STATUS_IS_OK(status)) {
5657                 printf("[7] unsetting delete_on_close on file failed !\n");
5658                 goto fail;
5659         }
5660
5661         status = cli_close(cli1, fnum1);
5662         if (!NT_STATUS_IS_OK(status)) {
5663                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5664                 goto fail;
5665         }
5666
5667         /* This next open should succeed - we reset the flag. */
5668         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5669         if (!NT_STATUS_IS_OK(status)) {
5670                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5671                 goto fail;
5672         }
5673
5674         status = cli_close(cli1, fnum1);
5675         if (!NT_STATUS_IS_OK(status)) {
5676                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5677                 goto fail;
5678         }
5679
5680         printf("seventh delete on close test succeeded.\n");
5681
5682         /* Test 8 ... */
5683         cli_setatr(cli1, fname, 0, 0);
5684         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5685
5686         if (!torture_open_connection(&cli2, 1)) {
5687                 printf("[8] failed to open second connection.\n");
5688                 goto fail;
5689         }
5690
5691         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5692
5693         status = cli_ntcreate(cli1, fname, 0,
5694                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5695                              FILE_ATTRIBUTE_NORMAL,
5696                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5697                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5698         if (!NT_STATUS_IS_OK(status)) {
5699                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5700                 goto fail;
5701         }
5702
5703         status = cli_ntcreate(cli2, fname, 0,
5704                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5705                              FILE_ATTRIBUTE_NORMAL,
5706                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5707                              FILE_OPEN, 0, 0, &fnum2, NULL);
5708         if (!NT_STATUS_IS_OK(status)) {
5709                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5710                 goto fail;
5711         }
5712
5713         status = cli_nt_delete_on_close(cli1, fnum1, true);
5714         if (!NT_STATUS_IS_OK(status)) {
5715                 printf("[8] setting delete_on_close on file failed !\n");
5716                 goto fail;
5717         }
5718
5719         status = cli_close(cli1, fnum1);
5720         if (!NT_STATUS_IS_OK(status)) {
5721                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5722                 goto fail;
5723         }
5724
5725         status = cli_close(cli2, fnum2);
5726         if (!NT_STATUS_IS_OK(status)) {
5727                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5728                 goto fail;
5729         }
5730
5731         /* This should fail.. */
5732         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5733         if (NT_STATUS_IS_OK(status)) {
5734                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5735                 goto fail;
5736         }
5737
5738         printf("eighth delete on close test succeeded.\n");
5739
5740         /* Test 9 ... */
5741
5742         /* This should fail - we need to set DELETE_ACCESS. */
5743         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5744                               FILE_ATTRIBUTE_NORMAL,
5745                               FILE_SHARE_NONE,
5746                               FILE_OVERWRITE_IF,
5747                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5748         if (NT_STATUS_IS_OK(status)) {
5749                 printf("[9] open of %s succeeded should have failed!\n", fname);
5750                 goto fail;
5751         }
5752
5753         printf("ninth delete on close test succeeded.\n");
5754
5755         /* Test 10 ... */
5756
5757         status = cli_ntcreate(cli1, fname, 0,
5758                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5759                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5760                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5761                              0, &fnum1, NULL);
5762         if (!NT_STATUS_IS_OK(status)) {
5763                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5764                 goto fail;
5765         }
5766
5767         /* This should delete the file. */
5768         status = cli_close(cli1, fnum1);
5769         if (!NT_STATUS_IS_OK(status)) {
5770                 printf("[10] close failed (%s)\n", nt_errstr(status));
5771                 goto fail;
5772         }
5773
5774         /* This should fail.. */
5775         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5776         if (NT_STATUS_IS_OK(status)) {
5777                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5778                 goto fail;
5779         }
5780
5781         printf("tenth delete on close test succeeded.\n");
5782
5783         /* Test 11 ... */
5784
5785         cli_setatr(cli1, fname, 0, 0);
5786         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5787
5788         /* Can we open a read-only file with delete access? */
5789
5790         /* Create a readonly file. */
5791         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5792                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5793                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5794         if (!NT_STATUS_IS_OK(status)) {
5795                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5796                 goto fail;
5797         }
5798
5799         status = cli_close(cli1, fnum1);
5800         if (!NT_STATUS_IS_OK(status)) {
5801                 printf("[11] close failed (%s)\n", nt_errstr(status));
5802                 goto fail;
5803         }
5804
5805         /* Now try open for delete access. */
5806         status = cli_ntcreate(cli1, fname, 0,
5807                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5808                              0,
5809                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5810                              FILE_OPEN, 0, 0, &fnum1, NULL);
5811         if (!NT_STATUS_IS_OK(status)) {
5812                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5813                 goto fail;
5814         }
5815
5816         cli_close(cli1, fnum1);
5817
5818         printf("eleventh delete on close test succeeded.\n");
5819
5820         /*
5821          * Test 12
5822          * like test 4 but with initial delete on close
5823          */
5824
5825         cli_setatr(cli1, fname, 0, 0);
5826         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5827
5828         status = cli_ntcreate(cli1, fname, 0,
5829                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5830                               FILE_ATTRIBUTE_NORMAL,
5831                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5832                               FILE_OVERWRITE_IF,
5833                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5834         if (!NT_STATUS_IS_OK(status)) {
5835                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5836                 goto fail;
5837         }
5838
5839         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5840                               FILE_ATTRIBUTE_NORMAL,
5841                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5842                               FILE_OPEN, 0, 0, &fnum2, NULL);
5843         if (!NT_STATUS_IS_OK(status)) {
5844                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5845                 goto fail;
5846         }
5847
5848         status = cli_close(cli1, fnum2);
5849         if (!NT_STATUS_IS_OK(status)) {
5850                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5851                 goto fail;
5852         }
5853
5854         status = cli_nt_delete_on_close(cli1, fnum1, true);
5855         if (!NT_STATUS_IS_OK(status)) {
5856                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5857                 goto fail;
5858         }
5859
5860         /* This should fail - no more opens once delete on close set. */
5861         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5862                               FILE_ATTRIBUTE_NORMAL,
5863                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5864                               FILE_OPEN, 0, 0, &fnum2, NULL);
5865         if (NT_STATUS_IS_OK(status)) {
5866                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5867                 goto fail;
5868         }
5869
5870         status = cli_nt_delete_on_close(cli1, fnum1, false);
5871         if (!NT_STATUS_IS_OK(status)) {
5872                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5873                 goto fail;
5874         }
5875
5876         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5877                               FILE_ATTRIBUTE_NORMAL,
5878                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5879                               FILE_OPEN, 0, 0, &fnum2, NULL);
5880         if (!NT_STATUS_IS_OK(status)) {
5881                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5882                 goto fail;
5883         }
5884
5885         status = cli_close(cli1, fnum2);
5886         if (!NT_STATUS_IS_OK(status)) {
5887                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5888                 goto fail;
5889         }
5890
5891         status = cli_close(cli1, fnum1);
5892         if (!NT_STATUS_IS_OK(status)) {
5893                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5894                 goto fail;
5895         }
5896
5897         /*
5898          * setting delete on close on the handle does
5899          * not unset the initial delete on close...
5900          */
5901         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5902                               FILE_ATTRIBUTE_NORMAL,
5903                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5904                               FILE_OPEN, 0, 0, &fnum2, NULL);
5905         if (NT_STATUS_IS_OK(status)) {
5906                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5907                 goto fail;
5908         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5909                 printf("ntcreate returned %s, expected "
5910                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5911                        nt_errstr(status));
5912                 goto fail;
5913         }
5914
5915         printf("twelfth delete on close test succeeded.\n");
5916
5917
5918         printf("finished delete test\n");
5919
5920         correct = true;
5921
5922   fail:
5923         /* FIXME: This will crash if we aborted before cli2 got
5924          * initialized, because these functions don't handle
5925          * uninitialized connections. */
5926
5927         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5928         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5929         cli_setatr(cli1, fname, 0, 0);
5930         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5931
5932         if (cli1 && !torture_close_connection(cli1)) {
5933                 correct = False;
5934         }
5935         if (cli2 && !torture_close_connection(cli2)) {
5936                 correct = False;
5937         }
5938         return correct;
5939 }
5940
5941 struct delete_stream_state {
5942         bool closed;
5943 };
5944
5945 static void delete_stream_unlinked(struct tevent_req *subreq);
5946 static void delete_stream_closed(struct tevent_req *subreq);
5947
5948 static struct tevent_req *delete_stream_send(
5949         TALLOC_CTX *mem_ctx,
5950         struct tevent_context *ev,
5951         struct cli_state *cli,
5952         const char *base_fname,
5953         uint16_t stream_fnum)
5954 {
5955         struct tevent_req *req = NULL, *subreq = NULL;
5956         struct delete_stream_state *state = NULL;
5957
5958         req = tevent_req_create(
5959                 mem_ctx, &state, struct delete_stream_state);
5960         if (req == NULL) {
5961                 return NULL;
5962         }
5963
5964         subreq = cli_unlink_send(
5965                 state,
5966                 ev,
5967                 cli,
5968                 base_fname,
5969                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5970         if (tevent_req_nomem(subreq, req)) {
5971                 return tevent_req_post(req, ev);
5972         }
5973         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5974
5975         subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5976         if (tevent_req_nomem(subreq, req)) {
5977                 return tevent_req_post(req, ev);
5978         }
5979         tevent_req_set_callback(subreq, delete_stream_closed, req);
5980
5981         return req;
5982 }
5983
5984 static void delete_stream_unlinked(struct tevent_req *subreq)
5985 {
5986         struct tevent_req *req = tevent_req_callback_data(
5987                 subreq, struct tevent_req);
5988         struct delete_stream_state *state = tevent_req_data(
5989                 req, struct delete_stream_state);
5990         NTSTATUS status;
5991
5992         status = cli_unlink_recv(subreq);
5993         TALLOC_FREE(subreq);
5994         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5995                 printf("cli_unlink returned %s\n",
5996                        nt_errstr(status));
5997                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5998                 return;
5999         }
6000         if (!state->closed) {
6001                 /* close reply should have come in first */
6002                 printf("Not closed\n");
6003                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6004                 return;
6005         }
6006         tevent_req_done(req);
6007 }
6008
6009 static void delete_stream_closed(struct tevent_req *subreq)
6010 {
6011         struct tevent_req *req = tevent_req_callback_data(
6012                 subreq, struct tevent_req);
6013         struct delete_stream_state *state = tevent_req_data(
6014                 req, struct delete_stream_state);
6015         NTSTATUS status;
6016
6017         status = cli_close_recv(subreq);
6018         TALLOC_FREE(subreq);
6019         if (tevent_req_nterror(req, status)) {
6020                 return;
6021         }
6022         /* also waiting for the unlink to come back */
6023         state->closed = true;
6024 }
6025
6026 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6027 {
6028         return tevent_req_simple_recv_ntstatus(req);
6029 }
6030
6031 static bool run_delete_stream(int dummy)
6032 {
6033         struct tevent_context *ev = NULL;
6034         struct tevent_req *req = NULL;
6035         struct cli_state *cli = NULL;
6036         const char fname[] = "delete_stream";
6037         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6038         uint16_t fnum1, fnum2;
6039         NTSTATUS status;
6040         bool ok;
6041
6042         printf("Starting stream delete test\n");
6043
6044         ok = torture_open_connection(&cli, 0);
6045         if (!ok) {
6046                 return false;
6047         }
6048
6049         cli_setatr(cli, fname, 0, 0);
6050         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6051
6052         /* Create the file. */
6053         status = cli_ntcreate(
6054                 cli,
6055                 fname,
6056                 0,
6057                 READ_CONTROL_ACCESS,
6058                 0,
6059                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6060                 FILE_CREATE,
6061                 0x0,
6062                 0x0,
6063                 &fnum1,
6064                 NULL);
6065         if (!NT_STATUS_IS_OK(status)) {
6066                 d_fprintf(stderr,
6067                           "cli_ntcreate of %s failed (%s)\n",
6068                           fname,
6069                           nt_errstr(status));
6070                 return false;
6071         }
6072         status = cli_close(cli, fnum1);
6073         if (!NT_STATUS_IS_OK(status)) {
6074                 d_fprintf(stderr,
6075                           "cli_close of %s failed (%s)\n",
6076                           fname,
6077                           nt_errstr(status));
6078                 return false;
6079         }
6080
6081         /* Now create the stream. */
6082         status = cli_ntcreate(
6083                 cli,
6084                 fname_stream,
6085                 0,
6086                 FILE_WRITE_DATA,
6087                 0,
6088                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6089                 FILE_CREATE,
6090                 0x0,
6091                 0x0,
6092                 &fnum1,
6093                 NULL);
6094
6095         if (!NT_STATUS_IS_OK(status)) {
6096                 d_fprintf(stderr,
6097                           "cli_ntcreate of %s failed (%s)\n",
6098                           fname_stream,
6099                           nt_errstr(status));
6100                 return false;
6101         }
6102
6103         /* open it a second time */
6104
6105         status = cli_ntcreate(
6106                 cli,
6107                 fname_stream,
6108                 0,
6109                 FILE_WRITE_DATA,
6110                 0,
6111                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6112                 FILE_OPEN,
6113                 0x0,
6114                 0x0,
6115                 &fnum2,
6116                 NULL);
6117
6118         if (!NT_STATUS_IS_OK(status)) {
6119                 d_fprintf(stderr,
6120                           "2nd cli_ntcreate of %s failed (%s)\n",
6121                           fname_stream,
6122                           nt_errstr(status));
6123                 return false;
6124         }
6125
6126         ev = samba_tevent_context_init(talloc_tos());
6127         if (ev == NULL) {
6128                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6129                 return false;
6130         }
6131
6132         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6133         if (req == NULL) {
6134                 d_fprintf(stderr, "delete_stream_send failed\n");
6135                 return false;
6136         }
6137
6138         ok = tevent_req_poll_ntstatus(req, ev, &status);
6139         if (!ok) {
6140                 d_fprintf(stderr,
6141                           "tevent_req_poll_ntstatus failed: %s\n",
6142                           nt_errstr(status));
6143                 return false;
6144         }
6145
6146         status = delete_stream_recv(req);
6147         TALLOC_FREE(req);
6148         if (!NT_STATUS_IS_OK(status)) {
6149                 d_fprintf(stderr,
6150                           "delete_stream failed: %s\n",
6151                           nt_errstr(status));
6152                 return false;
6153         }
6154
6155         status = cli_close(cli, fnum2);
6156         if (!NT_STATUS_IS_OK(status)) {
6157                 d_fprintf(stderr,
6158                           "close failed: %s\n",
6159                           nt_errstr(status));
6160                 return false;
6161         }
6162
6163         status = cli_unlink(
6164                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6165         if (!NT_STATUS_IS_OK(status)) {
6166                 d_fprintf(stderr,
6167                           "unlink failed: %s\n",
6168                           nt_errstr(status));
6169                 return false;
6170         }
6171
6172         return true;
6173 }
6174
6175 /*
6176   Exercise delete on close semantics - use on the PRINT1 share in torture
6177   testing.
6178  */
6179 static bool run_delete_print_test(int dummy)
6180 {
6181         struct cli_state *cli1 = NULL;
6182         const char *fname = "print_delete.file";
6183         uint16_t fnum1 = (uint16_t)-1;
6184         bool correct = false;
6185         const char *buf = "print file data\n";
6186         NTSTATUS status;
6187
6188         printf("starting print delete test\n");
6189
6190         if (!torture_open_connection(&cli1, 0)) {
6191                 return false;
6192         }
6193
6194         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6195
6196         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6197                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6198                               0, 0, &fnum1, NULL);
6199         if (!NT_STATUS_IS_OK(status)) {
6200                 printf("open of %s failed (%s)\n",
6201                         fname,
6202                         nt_errstr(status));
6203                 goto fail;
6204         }
6205
6206         status = cli_writeall(cli1,
6207                         fnum1,
6208                         0,
6209                         (const uint8_t *)buf,
6210                         0, /* offset */
6211                         strlen(buf), /* size */
6212                         NULL);
6213         if (!NT_STATUS_IS_OK(status)) {
6214                 printf("writing print file data failed (%s)\n",
6215                         nt_errstr(status));
6216                 goto fail;
6217         }
6218
6219         status = cli_nt_delete_on_close(cli1, fnum1, true);
6220         if (!NT_STATUS_IS_OK(status)) {
6221                 printf("setting delete_on_close failed (%s)\n",
6222                         nt_errstr(status));
6223                 goto fail;
6224         }
6225
6226         status = cli_close(cli1, fnum1);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 printf("close failed (%s)\n", nt_errstr(status));
6229                 goto fail;
6230         }
6231
6232         printf("finished print delete test\n");
6233
6234         correct = true;
6235
6236   fail:
6237
6238         if (fnum1 != (uint16_t)-1) {
6239                 cli_close(cli1, fnum1);
6240         }
6241
6242         if (cli1 && !torture_close_connection(cli1)) {
6243                 correct = false;
6244         }
6245         return correct;
6246 }
6247
6248 static bool run_deletetest_ln(int dummy)
6249 {
6250         struct cli_state *cli;
6251         const char *fname = "\\delete1";
6252         const char *fname_ln = "\\delete1_ln";
6253         uint16_t fnum;
6254         uint16_t fnum1;
6255         NTSTATUS status;
6256         bool correct = true;
6257         time_t t;
6258
6259         printf("starting deletetest-ln\n");
6260
6261         if (!torture_open_connection(&cli, 0)) {
6262                 return false;
6263         }
6264
6265         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6266         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6267
6268         smbXcli_conn_set_sockopt(cli->conn, sockops);
6269
6270         /* Create the file. */
6271         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6272         if (!NT_STATUS_IS_OK(status)) {
6273                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6274                 return false;
6275         }
6276
6277         status = cli_close(cli, fnum);
6278         if (!NT_STATUS_IS_OK(status)) {
6279                 printf("close1 failed (%s)\n", nt_errstr(status));
6280                 return false;
6281         }
6282
6283         /* Now create a hardlink. */
6284         status = cli_hardlink(cli, fname, fname_ln);
6285         if (!NT_STATUS_IS_OK(status)) {
6286                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6287                 return false;
6288         }
6289
6290         /* Open the original file. */
6291         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6292                         FILE_ATTRIBUTE_NORMAL,
6293                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6294                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6295         if (!NT_STATUS_IS_OK(status)) {
6296                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6297                 return false;
6298         }
6299
6300         /* Unlink the hard link path. */
6301         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6302                         FILE_ATTRIBUTE_NORMAL,
6303                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6304                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6305         if (!NT_STATUS_IS_OK(status)) {
6306                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6307                 return false;
6308         }
6309         status = cli_nt_delete_on_close(cli, fnum1, true);
6310         if (!NT_STATUS_IS_OK(status)) {
6311                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6312                         __location__, fname_ln, nt_errstr(status));
6313                 return false;
6314         }
6315
6316         status = cli_close(cli, fnum1);
6317         if (!NT_STATUS_IS_OK(status)) {
6318                 printf("close %s failed (%s)\n",
6319                         fname_ln, nt_errstr(status));
6320                 return false;
6321         }
6322
6323         status = cli_close(cli, fnum);
6324         if (!NT_STATUS_IS_OK(status)) {
6325                 printf("close %s failed (%s)\n",
6326                         fname, nt_errstr(status));
6327                 return false;
6328         }
6329
6330         /* Ensure the original file is still there. */
6331         status = cli_getatr(cli, fname, NULL, NULL, &t);
6332         if (!NT_STATUS_IS_OK(status)) {
6333                 printf("%s getatr on file %s failed (%s)\n",
6334                         __location__,
6335                         fname,
6336                         nt_errstr(status));
6337                 correct = False;
6338         }
6339
6340         /* Ensure the link path is gone. */
6341         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6342         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6343                 printf("%s, getatr for file %s returned wrong error code %s "
6344                         "- should have been deleted\n",
6345                         __location__,
6346                         fname_ln, nt_errstr(status));
6347                 correct = False;
6348         }
6349
6350         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6351         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6352
6353         if (!torture_close_connection(cli)) {
6354                 correct = false;
6355         }
6356
6357         printf("finished deletetest-ln\n");
6358
6359         return correct;
6360 }
6361
6362 /*
6363   print out server properties
6364  */
6365 static bool run_properties(int dummy)
6366 {
6367         struct cli_state *cli;
6368         bool correct = True;
6369
6370         printf("starting properties test\n");
6371
6372         ZERO_STRUCT(cli);
6373
6374         if (!torture_open_connection(&cli, 0)) {
6375                 return False;
6376         }
6377
6378         smbXcli_conn_set_sockopt(cli->conn, sockops);
6379
6380         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6381
6382         if (!torture_close_connection(cli)) {
6383                 correct = False;
6384         }
6385
6386         return correct;
6387 }
6388
6389
6390
6391 /* FIRST_DESIRED_ACCESS   0xf019f */
6392 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6393                                FILE_READ_EA|                           /* 0xf */ \
6394                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6395                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6396                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6397                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6398 /* SECOND_DESIRED_ACCESS  0xe0080 */
6399 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6400                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6401                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6402
6403 #if 0
6404 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6405                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6406                                FILE_READ_DATA|\
6407                                WRITE_OWNER_ACCESS                      /* */
6408 #endif
6409
6410 /*
6411   Test ntcreate calls made by xcopy
6412  */
6413 static bool run_xcopy(int dummy)
6414 {
6415         static struct cli_state *cli1;
6416         const char *fname = "\\test.txt";
6417         bool correct = True;
6418         uint16_t fnum1, fnum2;
6419         NTSTATUS status;
6420
6421         printf("starting xcopy test\n");
6422
6423         if (!torture_open_connection(&cli1, 0)) {
6424                 return False;
6425         }
6426
6427         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6428                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6429                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6430         if (!NT_STATUS_IS_OK(status)) {
6431                 printf("First open failed - %s\n", nt_errstr(status));
6432                 return False;
6433         }
6434
6435         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6436                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6437                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6438         if (!NT_STATUS_IS_OK(status)) {
6439                 printf("second open failed - %s\n", nt_errstr(status));
6440                 return False;
6441         }
6442
6443         if (!torture_close_connection(cli1)) {
6444                 correct = False;
6445         }
6446
6447         return correct;
6448 }
6449
6450 /*
6451   Test rename on files open with share delete and no share delete.
6452  */
6453 static bool run_rename(int dummy)
6454 {
6455         static struct cli_state *cli1;
6456         const char *fname = "\\test.txt";
6457         const char *fname1 = "\\test1.txt";
6458         bool correct = True;
6459         uint16_t fnum1;
6460         uint32_t attr;
6461         NTSTATUS status;
6462
6463         printf("starting rename test\n");
6464
6465         if (!torture_open_connection(&cli1, 0)) {
6466                 return False;
6467         }
6468
6469         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6470         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6471
6472         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6473                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6474                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6475         if (!NT_STATUS_IS_OK(status)) {
6476                 printf("First open failed - %s\n", nt_errstr(status));
6477                 return False;
6478         }
6479
6480         status = cli_rename(cli1, fname, fname1, false);
6481         if (!NT_STATUS_IS_OK(status)) {
6482                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6483         } else {
6484                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6485                 correct = False;
6486         }
6487
6488         status = cli_close(cli1, fnum1);
6489         if (!NT_STATUS_IS_OK(status)) {
6490                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6491                 return False;
6492         }
6493
6494         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6495         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6496         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6497 #if 0
6498                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6499 #else
6500                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6501 #endif
6502                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6503         if (!NT_STATUS_IS_OK(status)) {
6504                 printf("Second open failed - %s\n", nt_errstr(status));
6505                 return False;
6506         }
6507
6508         status = cli_rename(cli1, fname, fname1, false);
6509         if (!NT_STATUS_IS_OK(status)) {
6510                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6511                 correct = False;
6512         } else {
6513                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6514         }
6515
6516         status = cli_close(cli1, fnum1);
6517         if (!NT_STATUS_IS_OK(status)) {
6518                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6519                 return False;
6520         }
6521
6522         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6523         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6524
6525         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6526                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6527                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6528         if (!NT_STATUS_IS_OK(status)) {
6529                 printf("Third open failed - %s\n", nt_errstr(status));
6530                 return False;
6531         }
6532
6533
6534         status = cli_rename(cli1, fname, fname1, false);
6535         if (!NT_STATUS_IS_OK(status)) {
6536                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6537                 correct = False;
6538         } else {
6539                 printf("Third rename succeeded (SHARE_NONE)\n");
6540         }
6541
6542         status = cli_close(cli1, fnum1);
6543         if (!NT_STATUS_IS_OK(status)) {
6544                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6545                 return False;
6546         }
6547
6548         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6549         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6550
6551         /*----*/
6552
6553         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6554                               FILE_ATTRIBUTE_NORMAL,
6555                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6556                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6557         if (!NT_STATUS_IS_OK(status)) {
6558                 printf("Fourth open failed - %s\n", nt_errstr(status));
6559                 return False;
6560         }
6561
6562         status = cli_rename(cli1, fname, fname1, false);
6563         if (!NT_STATUS_IS_OK(status)) {
6564                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6565         } else {
6566                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6567                 correct = False;
6568         }
6569
6570         status = cli_close(cli1, fnum1);
6571         if (!NT_STATUS_IS_OK(status)) {
6572                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6573                 return False;
6574         }
6575
6576         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6577         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6578
6579         /*--*/
6580
6581         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6582                          FILE_ATTRIBUTE_NORMAL,
6583                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6584                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6585         if (!NT_STATUS_IS_OK(status)) {
6586                 printf("Fifth open failed - %s\n", nt_errstr(status));
6587                 return False;
6588         }
6589
6590         status = cli_rename(cli1, fname, fname1, false);
6591         if (!NT_STATUS_IS_OK(status)) {
6592                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6593                 correct = False;
6594         } else {
6595                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6596         }
6597
6598         /*--*/
6599         status = cli_close(cli1, fnum1);
6600         if (!NT_STATUS_IS_OK(status)) {
6601                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6602                 return False;
6603         }
6604
6605         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6606         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6607         if (!NT_STATUS_IS_OK(status)) {
6608                 printf("getatr on file %s failed - %s ! \n",
6609                         fname1, nt_errstr(status));
6610                 correct = False;
6611         } else {
6612                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6613                         printf("Renamed file %s has wrong attr 0x%x "
6614                                 "(should be 0x%x)\n",
6615                                 fname1,
6616                                 attr,
6617                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6618                         correct = False;
6619                 } else {
6620                         printf("Renamed file %s has archive bit set\n", fname1);
6621                 }
6622         }
6623
6624         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6625         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6626
6627         if (!torture_close_connection(cli1)) {
6628                 correct = False;
6629         }
6630
6631         return correct;
6632 }
6633
6634 /*
6635   Test rename into a directory with an ACL denying it.
6636  */
6637 static bool run_rename_access(int dummy)
6638 {
6639         static struct cli_state *cli = NULL;
6640         static struct cli_state *posix_cli = NULL;
6641         const char *src = "test.txt";
6642         const char *dname = "dir";
6643         const char *dst = "dir\\test.txt";
6644         const char *dsrc = "test.dir";
6645         const char *ddst = "dir\\test.dir";
6646         uint16_t fnum = (uint16_t)-1;
6647         struct security_descriptor *sd = NULL;
6648         struct security_descriptor *newsd = NULL;
6649         NTSTATUS status;
6650         TALLOC_CTX *frame = NULL;
6651
6652         frame = talloc_stackframe();
6653         printf("starting rename access test\n");
6654
6655         /* Windows connection. */
6656         if (!torture_open_connection(&cli, 0)) {
6657                 goto fail;
6658         }
6659
6660         smbXcli_conn_set_sockopt(cli->conn, sockops);
6661
6662         /* Posix connection. */
6663         if (!torture_open_connection(&posix_cli, 0)) {
6664                 goto fail;
6665         }
6666
6667         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6668
6669         status = torture_setup_unix_extensions(posix_cli);
6670         if (!NT_STATUS_IS_OK(status)) {
6671                 goto fail;
6672         }
6673
6674         /* Start with a clean slate. */
6675         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6676         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6677         cli_rmdir(cli, dsrc);
6678         cli_rmdir(cli, ddst);
6679         cli_rmdir(cli, dname);
6680
6681         /*
6682          * Setup the destination directory with a DENY ACE to
6683          * prevent new files within it.
6684          */
6685         status = cli_ntcreate(cli,
6686                                 dname,
6687                                 0,
6688                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6689                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6690                                         WRITE_OWNER_ACCESS,
6691                                 FILE_ATTRIBUTE_DIRECTORY,
6692                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6693                                 FILE_CREATE,
6694                                 FILE_DIRECTORY_FILE,
6695                                 0,
6696                                 &fnum,
6697                                 NULL);
6698         if (!NT_STATUS_IS_OK(status)) {
6699                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6700                 goto fail;
6701         }
6702
6703         status = cli_query_secdesc(cli,
6704                                 fnum,
6705                                 frame,
6706                                 &sd);
6707         if (!NT_STATUS_IS_OK(status)) {
6708                 printf("cli_query_secdesc failed for %s (%s)\n",
6709                         dname, nt_errstr(status));
6710                 goto fail;
6711         }
6712
6713         newsd = security_descriptor_dacl_create(frame,
6714                                         0,
6715                                         NULL,
6716                                         NULL,
6717                                         SID_WORLD,
6718                                         SEC_ACE_TYPE_ACCESS_DENIED,
6719                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6720                                         0,
6721                                         NULL);
6722         if (newsd == NULL) {
6723                 goto fail;
6724         }
6725         sd->dacl = security_acl_concatenate(frame,
6726                                         newsd->dacl,
6727                                         sd->dacl);
6728         if (sd->dacl == NULL) {
6729                 goto fail;
6730         }
6731         status = cli_set_secdesc(cli, fnum, sd);
6732         if (!NT_STATUS_IS_OK(status)) {
6733                 printf("cli_set_secdesc failed for %s (%s)\n",
6734                         dname, nt_errstr(status));
6735                 goto fail;
6736         }
6737         status = cli_close(cli, fnum);
6738         if (!NT_STATUS_IS_OK(status)) {
6739                 printf("close failed for %s (%s)\n",
6740                         dname, nt_errstr(status));
6741                 goto fail;
6742         }
6743         /* Now go around the back and chmod to 777 via POSIX. */
6744         status = cli_posix_chmod(posix_cli, dname, 0777);
6745         if (!NT_STATUS_IS_OK(status)) {
6746                 printf("cli_posix_chmod failed for %s (%s)\n",
6747                         dname, nt_errstr(status));
6748                 goto fail;
6749         }
6750
6751         /* Check we can't create a file within dname via Windows. */
6752         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6753         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6754                 cli_close(posix_cli, fnum);
6755                 printf("Create of %s should be ACCESS denied, was %s\n",
6756                         dst, nt_errstr(status));
6757                 goto fail;
6758         }
6759
6760         /* Make the sample file/directory. */
6761         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6762         if (!NT_STATUS_IS_OK(status)) {
6763                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6764                 goto fail;
6765         }
6766         status = cli_close(cli, fnum);
6767         if (!NT_STATUS_IS_OK(status)) {
6768                 printf("cli_close failed (%s)\n", nt_errstr(status));
6769                 goto fail;
6770         }
6771
6772         status = cli_mkdir(cli, dsrc);
6773         if (!NT_STATUS_IS_OK(status)) {
6774                 printf("cli_mkdir of %s failed (%s)\n",
6775                         dsrc, nt_errstr(status));
6776                 goto fail;
6777         }
6778
6779         /*
6780          * OK - renames of the new file and directory into the
6781          * dst directory should fail.
6782          */
6783
6784         status = cli_rename(cli, src, dst, false);
6785         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6786                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6787                         src, dst, nt_errstr(status));
6788                 goto fail;
6789         }
6790         status = cli_rename(cli, dsrc, ddst, false);
6791         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6792                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6793                         src, dst, nt_errstr(status));
6794                 goto fail;
6795         }
6796
6797         TALLOC_FREE(frame);
6798         return true;
6799
6800   fail:
6801
6802         if (posix_cli) {
6803                 torture_close_connection(posix_cli);
6804         }
6805
6806         if (cli) {
6807                 if (fnum != (uint16_t)-1) {
6808                         cli_close(cli, fnum);
6809                 }
6810                 cli_unlink(cli, src,
6811                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6812                 cli_unlink(cli, dst,
6813                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6814                 cli_rmdir(cli, dsrc);
6815                 cli_rmdir(cli, ddst);
6816                 cli_rmdir(cli, dname);
6817
6818                 torture_close_connection(cli);
6819         }
6820
6821         TALLOC_FREE(frame);
6822         return false;
6823 }
6824
6825 /*
6826   Test owner rights ACE.
6827  */
6828 static bool run_owner_rights(int dummy)
6829 {
6830         static struct cli_state *cli = NULL;
6831         const char *fname = "owner_rights.txt";
6832         uint16_t fnum = (uint16_t)-1;
6833         struct security_descriptor *sd = NULL;
6834         struct security_descriptor *newsd = NULL;
6835         NTSTATUS status;
6836         TALLOC_CTX *frame = NULL;
6837
6838         frame = talloc_stackframe();
6839         printf("starting owner rights test\n");
6840
6841         /* Windows connection. */
6842         if (!torture_open_connection(&cli, 0)) {
6843                 goto fail;
6844         }
6845
6846         smbXcli_conn_set_sockopt(cli->conn, sockops);
6847
6848         /* Start with a clean slate. */
6849         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6850
6851         /* Create the test file. */
6852         /* Now try and open for read and write-dac. */
6853         status = cli_ntcreate(cli,
6854                                 fname,
6855                                 0,
6856                                 GENERIC_ALL_ACCESS,
6857                                 FILE_ATTRIBUTE_NORMAL,
6858                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6859                                         FILE_SHARE_DELETE,
6860                                 FILE_CREATE,
6861                                 0,
6862                                 0,
6863                                 &fnum,
6864                                 NULL);
6865         if (!NT_STATUS_IS_OK(status)) {
6866                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6867                 goto fail;
6868         }
6869
6870         /* Get the original SD. */
6871         status = cli_query_secdesc(cli,
6872                                 fnum,
6873                                 frame,
6874                                 &sd);
6875         if (!NT_STATUS_IS_OK(status)) {
6876                 printf("cli_query_secdesc failed for %s (%s)\n",
6877                         fname, nt_errstr(status));
6878                 goto fail;
6879         }
6880
6881         /*
6882          * Add an "owner-rights" ACE denying WRITE_DATA,
6883          * and an "owner-rights" ACE allowing READ_DATA.
6884          */
6885
6886         newsd = security_descriptor_dacl_create(frame,
6887                                         0,
6888                                         NULL,
6889                                         NULL,
6890                                         SID_OWNER_RIGHTS,
6891                                         SEC_ACE_TYPE_ACCESS_DENIED,
6892                                         FILE_WRITE_DATA,
6893                                         0,
6894                                         SID_OWNER_RIGHTS,
6895                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6896                                         FILE_READ_DATA,
6897                                         0,
6898                                         NULL);
6899         if (newsd == NULL) {
6900                 goto fail;
6901         }
6902         sd->dacl = security_acl_concatenate(frame,
6903                                         newsd->dacl,
6904                                         sd->dacl);
6905         if (sd->dacl == NULL) {
6906                 goto fail;
6907         }
6908         status = cli_set_secdesc(cli, fnum, sd);
6909         if (!NT_STATUS_IS_OK(status)) {
6910                 printf("cli_set_secdesc failed for %s (%s)\n",
6911                         fname, nt_errstr(status));
6912                 goto fail;
6913         }
6914         status = cli_close(cli, fnum);
6915         if (!NT_STATUS_IS_OK(status)) {
6916                 printf("close failed for %s (%s)\n",
6917                         fname, nt_errstr(status));
6918                 goto fail;
6919         }
6920         fnum = (uint16_t)-1;
6921
6922         /* Try and open for FILE_WRITE_DATA */
6923         status = cli_ntcreate(cli,
6924                                 fname,
6925                                 0,
6926                                 FILE_WRITE_DATA,
6927                                 FILE_ATTRIBUTE_NORMAL,
6928                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6929                                         FILE_SHARE_DELETE,
6930                                 FILE_OPEN,
6931                                 0,
6932                                 0,
6933                                 &fnum,
6934                                 NULL);
6935         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6936                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6937                 goto fail;
6938         }
6939
6940         /* Now try and open for FILE_READ_DATA */
6941         status = cli_ntcreate(cli,
6942                                 fname,
6943                                 0,
6944                                 FILE_READ_DATA,
6945                                 FILE_ATTRIBUTE_NORMAL,
6946                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6947                                         FILE_SHARE_DELETE,
6948                                 FILE_OPEN,
6949                                 0,
6950                                 0,
6951                                 &fnum,
6952                                 NULL);
6953         if (!NT_STATUS_IS_OK(status)) {
6954                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6955                 goto fail;
6956         }
6957
6958         status = cli_close(cli, fnum);
6959         if (!NT_STATUS_IS_OK(status)) {
6960                 printf("close failed for %s (%s)\n",
6961                         fname, nt_errstr(status));
6962                 goto fail;
6963         }
6964
6965         /* Restore clean slate. */
6966         TALLOC_FREE(sd);
6967         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6968
6969         /* Create the test file. */
6970         status = cli_ntcreate(cli,
6971                                 fname,
6972                                 0,
6973                                 GENERIC_ALL_ACCESS,
6974                                 FILE_ATTRIBUTE_NORMAL,
6975                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6976                                         FILE_SHARE_DELETE,
6977                                 FILE_CREATE,
6978                                 0,
6979                                 0,
6980                                 &fnum,
6981                                 NULL);
6982         if (!NT_STATUS_IS_OK(status)) {
6983                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6984                 goto fail;
6985         }
6986
6987         /* Get the original SD. */
6988         status = cli_query_secdesc(cli,
6989                                 fnum,
6990                                 frame,
6991                                 &sd);
6992         if (!NT_STATUS_IS_OK(status)) {
6993                 printf("cli_query_secdesc failed for %s (%s)\n",
6994                         fname, nt_errstr(status));
6995                 goto fail;
6996         }
6997
6998         /*
6999          * Add an "owner-rights ACE denying WRITE_DATA,
7000          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7001          */
7002
7003         newsd = security_descriptor_dacl_create(frame,
7004                                         0,
7005                                         NULL,
7006                                         NULL,
7007                                         SID_OWNER_RIGHTS,
7008                                         SEC_ACE_TYPE_ACCESS_DENIED,
7009                                         FILE_WRITE_DATA,
7010                                         0,
7011                                         SID_OWNER_RIGHTS,
7012                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7013                                         FILE_READ_DATA|FILE_WRITE_DATA,
7014                                         0,
7015                                         NULL);
7016         if (newsd == NULL) {
7017                 goto fail;
7018         }
7019         sd->dacl = security_acl_concatenate(frame,
7020                                         newsd->dacl,
7021                                         sd->dacl);
7022         if (sd->dacl == NULL) {
7023                 goto fail;
7024         }
7025         status = cli_set_secdesc(cli, fnum, sd);
7026         if (!NT_STATUS_IS_OK(status)) {
7027                 printf("cli_set_secdesc failed for %s (%s)\n",
7028                         fname, nt_errstr(status));
7029                 goto fail;
7030         }
7031         status = cli_close(cli, fnum);
7032         if (!NT_STATUS_IS_OK(status)) {
7033                 printf("close failed for %s (%s)\n",
7034                         fname, nt_errstr(status));
7035                 goto fail;
7036         }
7037         fnum = (uint16_t)-1;
7038
7039         /* Try and open for FILE_WRITE_DATA */
7040         status = cli_ntcreate(cli,
7041                                 fname,
7042                                 0,
7043                                 FILE_WRITE_DATA,
7044                                 FILE_ATTRIBUTE_NORMAL,
7045                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7046                                         FILE_SHARE_DELETE,
7047                                 FILE_OPEN,
7048                                 0,
7049                                 0,
7050                                 &fnum,
7051                                 NULL);
7052         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7053                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7054                 goto fail;
7055         }
7056
7057         /* Now try and open for FILE_READ_DATA */
7058         status = cli_ntcreate(cli,
7059                                 fname,
7060                                 0,
7061                                 FILE_READ_DATA,
7062                                 FILE_ATTRIBUTE_NORMAL,
7063                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7064                                         FILE_SHARE_DELETE,
7065                                 FILE_OPEN,
7066                                 0,
7067                                 0,
7068                                 &fnum,
7069                                 NULL);
7070         if (!NT_STATUS_IS_OK(status)) {
7071                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7072                 goto fail;
7073         }
7074
7075         status = cli_close(cli, fnum);
7076         if (!NT_STATUS_IS_OK(status)) {
7077                 printf("close failed for %s (%s)\n",
7078                         fname, nt_errstr(status));
7079                 goto fail;
7080         }
7081
7082         /* Restore clean slate. */
7083         TALLOC_FREE(sd);
7084         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7085
7086
7087         /* Create the test file. */
7088         status = cli_ntcreate(cli,
7089                                 fname,
7090                                 0,
7091                                 GENERIC_ALL_ACCESS,
7092                                 FILE_ATTRIBUTE_NORMAL,
7093                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7094                                         FILE_SHARE_DELETE,
7095                                 FILE_CREATE,
7096                                 0,
7097                                 0,
7098                                 &fnum,
7099                                 NULL);
7100         if (!NT_STATUS_IS_OK(status)) {
7101                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7102                 goto fail;
7103         }
7104
7105         /* Get the original SD. */
7106         status = cli_query_secdesc(cli,
7107                                 fnum,
7108                                 frame,
7109                                 &sd);
7110         if (!NT_STATUS_IS_OK(status)) {
7111                 printf("cli_query_secdesc failed for %s (%s)\n",
7112                         fname, nt_errstr(status));
7113                 goto fail;
7114         }
7115
7116         /*
7117          * Add an "authenticated users" ACE allowing READ_DATA,
7118          * add an "owner-rights" denying READ_DATA,
7119          * and an "authenticated users" ACE allowing WRITE_DATA.
7120          */
7121
7122         newsd = security_descriptor_dacl_create(frame,
7123                                         0,
7124                                         NULL,
7125                                         NULL,
7126                                         SID_NT_AUTHENTICATED_USERS,
7127                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7128                                         FILE_READ_DATA,
7129                                         0,
7130                                         SID_OWNER_RIGHTS,
7131                                         SEC_ACE_TYPE_ACCESS_DENIED,
7132                                         FILE_READ_DATA,
7133                                         0,
7134                                         SID_NT_AUTHENTICATED_USERS,
7135                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7136                                         FILE_WRITE_DATA,
7137                                         0,
7138                                         NULL);
7139         if (newsd == NULL) {
7140                 printf("newsd == NULL\n");
7141                 goto fail;
7142         }
7143         sd->dacl = security_acl_concatenate(frame,
7144                                         newsd->dacl,
7145                                         sd->dacl);
7146         if (sd->dacl == NULL) {
7147                 printf("sd->dacl == NULL\n");
7148                 goto fail;
7149         }
7150         status = cli_set_secdesc(cli, fnum, sd);
7151         if (!NT_STATUS_IS_OK(status)) {
7152                 printf("cli_set_secdesc failed for %s (%s)\n",
7153                         fname, nt_errstr(status));
7154                 goto fail;
7155         }
7156         status = cli_close(cli, fnum);
7157         if (!NT_STATUS_IS_OK(status)) {
7158                 printf("close failed for %s (%s)\n",
7159                         fname, nt_errstr(status));
7160                 goto fail;
7161         }
7162         fnum = (uint16_t)-1;
7163
7164         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7165         status = cli_ntcreate(cli,
7166                                 fname,
7167                                 0,
7168                                 FILE_READ_DATA|FILE_WRITE_DATA,
7169                                 FILE_ATTRIBUTE_NORMAL,
7170                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7171                                         FILE_SHARE_DELETE,
7172                                 FILE_OPEN,
7173                                 0,
7174                                 0,
7175                                 &fnum,
7176                                 NULL);
7177         if (!NT_STATUS_IS_OK(status)) {
7178                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7179                 goto fail;
7180         }
7181
7182         status = cli_close(cli, fnum);
7183         if (!NT_STATUS_IS_OK(status)) {
7184                 printf("close failed for %s (%s)\n",
7185                         fname, nt_errstr(status));
7186                 goto fail;
7187         }
7188
7189         cli_unlink(cli, fname,
7190                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7191
7192         TALLOC_FREE(frame);
7193         return true;
7194
7195   fail:
7196
7197         if (cli) {
7198                 if (fnum != (uint16_t)-1) {
7199                         cli_close(cli, fnum);
7200                 }
7201                 cli_unlink(cli, fname,
7202                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7203                 torture_close_connection(cli);
7204         }
7205
7206         TALLOC_FREE(frame);
7207         return false;
7208 }
7209
7210 /*
7211  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7212  * Note this test only works with a user with SeSecurityPrivilege set.
7213  *
7214  * NB. This is also tested in samba3.base.createx_access
7215  * but this makes it very explicit what we're looking for.
7216  */
7217 static bool run_smb1_system_security(int dummy)
7218 {
7219         static struct cli_state *cli = NULL;
7220         const char *fname = "system_security.txt";
7221         uint16_t fnum = (uint16_t)-1;
7222         NTSTATUS status;
7223         TALLOC_CTX *frame = NULL;
7224
7225         frame = talloc_stackframe();
7226         printf("starting smb1 system security test\n");
7227
7228         /* SMB1 connection - torture_open_connection() forces this. */
7229         if (!torture_open_connection(&cli, 0)) {
7230                 goto fail;
7231         }
7232
7233         smbXcli_conn_set_sockopt(cli->conn, sockops);
7234
7235         /* Start with a clean slate. */
7236         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7237
7238         /* Create the test file. */
7239         status = cli_ntcreate(cli,
7240                                 fname,
7241                                 0,
7242                                 GENERIC_ALL_ACCESS,
7243                                 FILE_ATTRIBUTE_NORMAL,
7244                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7245                                         FILE_SHARE_DELETE,
7246                                 FILE_CREATE,
7247                                 0,
7248                                 0,
7249                                 &fnum,
7250                                 NULL);
7251         if (!NT_STATUS_IS_OK(status)) {
7252                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7253                 goto fail;
7254         }
7255
7256         status = cli_close(cli, fnum);
7257
7258         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7259         /*
7260          * On SMB1 this succeeds - SMB2 it fails,
7261          * see the SMB2-SACL test.
7262          */
7263         status = cli_ntcreate(cli,
7264                                 fname,
7265                                 0,
7266                                 SEC_FLAG_SYSTEM_SECURITY,
7267                                 FILE_ATTRIBUTE_NORMAL,
7268                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7269                                         FILE_SHARE_DELETE,
7270                                 FILE_OPEN,
7271                                 0,
7272                                 0,
7273                                 &fnum,
7274                                 NULL);
7275         if (!NT_STATUS_IS_OK(status)) {
7276                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7277                 goto fail;
7278         }
7279
7280         status = cli_close(cli, fnum);
7281
7282         cli_unlink(cli, fname,
7283                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7284
7285         torture_close_connection(cli);
7286         TALLOC_FREE(frame);
7287         return true;
7288
7289   fail:
7290
7291         if (cli) {
7292                 if (fnum != (uint16_t)-1) {
7293                         cli_close(cli, fnum);
7294                 }
7295                 cli_unlink(cli, fname,
7296                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7297                 torture_close_connection(cli);
7298         }
7299
7300         TALLOC_FREE(frame);
7301         return false;
7302 }
7303
7304 static bool run_pipe_number(int dummy)
7305 {
7306         struct cli_state *cli1;
7307         const char *pipe_name = "\\SPOOLSS";
7308         uint16_t fnum;
7309         int num_pipes = 0;
7310         NTSTATUS status;
7311
7312         printf("starting pipenumber test\n");
7313         if (!torture_open_connection(&cli1, 0)) {
7314                 return False;
7315         }
7316
7317         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7318         while(1) {
7319                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7320                                       FILE_ATTRIBUTE_NORMAL,
7321                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7322                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7323                 if (!NT_STATUS_IS_OK(status)) {
7324                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7325                         break;
7326                 }
7327                 num_pipes++;
7328                 printf("\r%6d", num_pipes);
7329         }
7330
7331         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7332         torture_close_connection(cli1);
7333         return True;
7334 }
7335
7336 /*
7337   Test open mode returns on read-only files.
7338  */
7339 static bool run_opentest(int dummy)
7340 {
7341         static struct cli_state *cli1;
7342         static struct cli_state *cli2;
7343         const char *fname = "\\readonly.file";
7344         uint16_t fnum1, fnum2;
7345         char buf[20];
7346         off_t fsize;
7347         bool correct = True;
7348         char *tmp_path;
7349         NTSTATUS status;
7350
7351         printf("starting open test\n");
7352
7353         if (!torture_open_connection(&cli1, 0)) {
7354                 return False;
7355         }
7356
7357         cli_setatr(cli1, fname, 0, 0);
7358         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7359
7360         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7361
7362         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7363         if (!NT_STATUS_IS_OK(status)) {
7364                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7365                 return False;
7366         }
7367
7368         status = cli_close(cli1, fnum1);
7369         if (!NT_STATUS_IS_OK(status)) {
7370                 printf("close2 failed (%s)\n", nt_errstr(status));
7371                 return False;
7372         }
7373
7374         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7375         if (!NT_STATUS_IS_OK(status)) {
7376                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7377                 return False;
7378         }
7379
7380         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7381         if (!NT_STATUS_IS_OK(status)) {
7382                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7383                 return False;
7384         }
7385
7386         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7387         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7388
7389         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7390                         NT_STATUS_ACCESS_DENIED)) {
7391                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7392         }
7393
7394         printf("finished open test 1\n");
7395
7396         cli_close(cli1, fnum1);
7397
7398         /* Now try not readonly and ensure ERRbadshare is returned. */
7399
7400         cli_setatr(cli1, fname, 0, 0);
7401
7402         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7403         if (!NT_STATUS_IS_OK(status)) {
7404                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7405                 return False;
7406         }
7407
7408         /* This will fail - but the error should be ERRshare. */
7409         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7410
7411         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7412                         NT_STATUS_SHARING_VIOLATION)) {
7413                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7414         }
7415
7416         status = cli_close(cli1, fnum1);
7417         if (!NT_STATUS_IS_OK(status)) {
7418                 printf("close2 failed (%s)\n", nt_errstr(status));
7419                 return False;
7420         }
7421
7422         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7423
7424         printf("finished open test 2\n");
7425
7426         /* Test truncate open disposition on file opened for read. */
7427         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7428         if (!NT_STATUS_IS_OK(status)) {
7429                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7430                 return False;
7431         }
7432
7433         /* write 20 bytes. */
7434
7435         memset(buf, '\0', 20);
7436
7437         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7438         if (!NT_STATUS_IS_OK(status)) {
7439                 printf("write failed (%s)\n", nt_errstr(status));
7440                 correct = False;
7441         }
7442
7443         status = cli_close(cli1, fnum1);
7444         if (!NT_STATUS_IS_OK(status)) {
7445                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7446                 return False;
7447         }
7448
7449         /* Ensure size == 20. */
7450         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7451         if (!NT_STATUS_IS_OK(status)) {
7452                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7453                 return False;
7454         }
7455
7456         if (fsize != 20) {
7457                 printf("(3) file size != 20\n");
7458                 return False;
7459         }
7460
7461         /* Now test if we can truncate a file opened for readonly. */
7462         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7463         if (!NT_STATUS_IS_OK(status)) {
7464                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7465                 return False;
7466         }
7467
7468         status = cli_close(cli1, fnum1);
7469         if (!NT_STATUS_IS_OK(status)) {
7470                 printf("close2 failed (%s)\n", nt_errstr(status));
7471                 return False;
7472         }
7473
7474         /* Ensure size == 0. */
7475         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7476         if (!NT_STATUS_IS_OK(status)) {
7477                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7478                 return False;
7479         }
7480
7481         if (fsize != 0) {
7482                 printf("(3) file size != 0\n");
7483                 return False;
7484         }
7485         printf("finished open test 3\n");
7486
7487         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7488
7489         printf("Do ctemp tests\n");
7490         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7491         if (!NT_STATUS_IS_OK(status)) {
7492                 printf("ctemp failed (%s)\n", nt_errstr(status));
7493                 return False;
7494         }
7495
7496         printf("ctemp gave path %s\n", tmp_path);
7497         status = cli_close(cli1, fnum1);
7498         if (!NT_STATUS_IS_OK(status)) {
7499                 printf("close of temp failed (%s)\n", nt_errstr(status));
7500         }
7501
7502         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7503         if (!NT_STATUS_IS_OK(status)) {
7504                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7505         }
7506
7507         /* Test the non-io opens... */
7508
7509         if (!torture_open_connection(&cli2, 1)) {
7510                 return False;
7511         }
7512
7513         cli_setatr(cli2, fname, 0, 0);
7514         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7515
7516         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7517
7518         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7519         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7520                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7521                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7522         if (!NT_STATUS_IS_OK(status)) {
7523                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7524                 return False;
7525         }
7526
7527         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7528                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7529                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7530         if (!NT_STATUS_IS_OK(status)) {
7531                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7532                 return False;
7533         }
7534
7535         status = cli_close(cli1, fnum1);
7536         if (!NT_STATUS_IS_OK(status)) {
7537                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7538                 return False;
7539         }
7540
7541         status = cli_close(cli2, fnum2);
7542         if (!NT_STATUS_IS_OK(status)) {
7543                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7544                 return False;
7545         }
7546
7547         printf("non-io open test #1 passed.\n");
7548
7549         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7550
7551         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7552
7553         status = cli_ntcreate(cli1, fname, 0,
7554                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7555                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7556                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7557         if (!NT_STATUS_IS_OK(status)) {
7558                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7559                 return False;
7560         }
7561
7562         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7563                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7564                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7565         if (!NT_STATUS_IS_OK(status)) {
7566                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7567                 return False;
7568         }
7569
7570         status = cli_close(cli1, fnum1);
7571         if (!NT_STATUS_IS_OK(status)) {
7572                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7573                 return False;
7574         }
7575
7576         status = cli_close(cli2, fnum2);
7577         if (!NT_STATUS_IS_OK(status)) {
7578                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7579                 return False;
7580         }
7581
7582         printf("non-io open test #2 passed.\n");
7583
7584         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7585
7586         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7587
7588         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7589                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7590                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7591         if (!NT_STATUS_IS_OK(status)) {
7592                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7593                 return False;
7594         }
7595
7596         status = cli_ntcreate(cli2, fname, 0,
7597                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7598                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7599                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7600         if (!NT_STATUS_IS_OK(status)) {
7601                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7602                 return False;
7603         }
7604
7605         status = cli_close(cli1, fnum1);
7606         if (!NT_STATUS_IS_OK(status)) {
7607                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7608                 return False;
7609         }
7610
7611         status = cli_close(cli2, fnum2);
7612         if (!NT_STATUS_IS_OK(status)) {
7613                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7614                 return False;
7615         }
7616
7617         printf("non-io open test #3 passed.\n");
7618
7619         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7620
7621         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7622
7623         status = cli_ntcreate(cli1, fname, 0,
7624                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7625                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7626                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7627         if (!NT_STATUS_IS_OK(status)) {
7628                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7629                 return False;
7630         }
7631
7632         status = cli_ntcreate(cli2, fname, 0,
7633                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7634                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7635                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7636         if (NT_STATUS_IS_OK(status)) {
7637                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7638                 return False;
7639         }
7640
7641         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7642
7643         status = cli_close(cli1, fnum1);
7644         if (!NT_STATUS_IS_OK(status)) {
7645                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7646                 return False;
7647         }
7648
7649         printf("non-io open test #4 passed.\n");
7650
7651         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7652
7653         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7654
7655         status = cli_ntcreate(cli1, fname, 0,
7656                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7657                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7658                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7659         if (!NT_STATUS_IS_OK(status)) {
7660                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7661                 return False;
7662         }
7663
7664         status = cli_ntcreate(cli2, fname, 0,
7665                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7666                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7667                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7668         if (!NT_STATUS_IS_OK(status)) {
7669                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7670                 return False;
7671         }
7672
7673         status = cli_close(cli1, fnum1);
7674         if (!NT_STATUS_IS_OK(status)) {
7675                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7676                 return False;
7677         }
7678
7679         status = cli_close(cli2, fnum2);
7680         if (!NT_STATUS_IS_OK(status)) {
7681                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7682                 return False;
7683         }
7684
7685         printf("non-io open test #5 passed.\n");
7686
7687         printf("TEST #6 testing 1 non-io open, one io open\n");
7688
7689         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7690
7691         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7692                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7693                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7694         if (!NT_STATUS_IS_OK(status)) {
7695                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7696                 return False;
7697         }
7698
7699         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7700                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7701                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7702         if (!NT_STATUS_IS_OK(status)) {
7703                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7704                 return False;
7705         }
7706
7707         status = cli_close(cli1, fnum1);
7708         if (!NT_STATUS_IS_OK(status)) {
7709                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7710                 return False;
7711         }
7712
7713         status = cli_close(cli2, fnum2);
7714         if (!NT_STATUS_IS_OK(status)) {
7715                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7716                 return False;
7717         }
7718
7719         printf("non-io open test #6 passed.\n");
7720
7721         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7722
7723         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7724
7725         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7726                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7727                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7728         if (!NT_STATUS_IS_OK(status)) {
7729                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7730                 return False;
7731         }
7732
7733         status = cli_ntcreate(cli2, fname, 0,
7734                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7735                               FILE_ATTRIBUTE_NORMAL,
7736                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7737                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7738         if (NT_STATUS_IS_OK(status)) {
7739                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7740                 return False;
7741         }
7742
7743         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7744
7745         status = cli_close(cli1, fnum1);
7746         if (!NT_STATUS_IS_OK(status)) {
7747                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7748                 return False;
7749         }
7750
7751         printf("non-io open test #7 passed.\n");
7752
7753         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7754
7755         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7756         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7757                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7758                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7759         if (!NT_STATUS_IS_OK(status)) {
7760                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7761                 correct = false;
7762                 goto out;
7763         }
7764
7765         /* Write to ensure we have to update the file time. */
7766         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7767                               NULL);
7768         if (!NT_STATUS_IS_OK(status)) {
7769                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7770                 correct = false;
7771                 goto out;
7772         }
7773
7774         status = cli_close(cli1, fnum1);
7775         if (!NT_STATUS_IS_OK(status)) {
7776                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7777                 correct = false;
7778         }
7779
7780   out:
7781
7782         if (!torture_close_connection(cli1)) {
7783                 correct = False;
7784         }
7785         if (!torture_close_connection(cli2)) {
7786                 correct = False;
7787         }
7788
7789         return correct;
7790 }
7791
7792 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7793 {
7794         uint16_t major, minor;
7795         uint32_t caplow, caphigh;
7796         NTSTATUS status;
7797
7798         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7799                 printf("Server doesn't support UNIX CIFS extensions.\n");
7800                 return NT_STATUS_NOT_SUPPORTED;
7801         }
7802
7803         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7804                                              &caphigh);
7805         if (!NT_STATUS_IS_OK(status)) {
7806                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7807                        nt_errstr(status));
7808                 return status;
7809         }
7810
7811         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7812                                                       caplow, caphigh);
7813         if (!NT_STATUS_IS_OK(status)) {
7814                 printf("Server doesn't support setting UNIX CIFS extensions: "
7815                        "%s.\n", nt_errstr(status));
7816                 return status;
7817         }
7818
7819         return NT_STATUS_OK;
7820 }
7821
7822 /*
7823   Test POSIX open /mkdir calls.
7824  */
7825 static bool run_simple_posix_open_test(int dummy)
7826 {
7827         static struct cli_state *cli1;
7828         const char *fname = "posix:file";
7829         const char *hname = "posix:hlink";
7830         const char *sname = "posix:symlink";
7831         const char *dname = "posix:dir";
7832         char buf[10];
7833         char *target = NULL;
7834         uint16_t fnum1 = (uint16_t)-1;
7835         SMB_STRUCT_STAT sbuf;
7836         bool correct = false;
7837         NTSTATUS status;
7838         size_t nread;
7839         const char *fname_windows = "windows_file";
7840         uint16_t fnum2 = (uint16_t)-1;
7841         bool ok;
7842
7843         printf("Starting simple POSIX open test\n");
7844
7845         if (!torture_open_connection(&cli1, 0)) {
7846                 return false;
7847         }
7848
7849         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7850
7851         status = torture_setup_unix_extensions(cli1);
7852         if (!NT_STATUS_IS_OK(status)) {
7853                 return false;
7854         }
7855
7856         cli_setatr(cli1, fname, 0, 0);
7857         cli_posix_unlink(cli1, fname);
7858         cli_setatr(cli1, dname, 0, 0);
7859         cli_posix_rmdir(cli1, dname);
7860         cli_setatr(cli1, hname, 0, 0);
7861         cli_posix_unlink(cli1, hname);
7862         cli_setatr(cli1, sname, 0, 0);
7863         cli_posix_unlink(cli1, sname);
7864         cli_setatr(cli1, fname_windows, 0, 0);
7865         cli_posix_unlink(cli1, fname_windows);
7866
7867         /* Create a directory. */
7868         status = cli_posix_mkdir(cli1, dname, 0777);
7869         if (!NT_STATUS_IS_OK(status)) {
7870                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7871                 goto out;
7872         }
7873
7874         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7875                                 0600, &fnum1);
7876         if (!NT_STATUS_IS_OK(status)) {
7877                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7878                 goto out;
7879         }
7880
7881         /* Test ftruncate - set file size. */
7882         status = cli_ftruncate(cli1, fnum1, 1000);
7883         if (!NT_STATUS_IS_OK(status)) {
7884                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7885                 goto out;
7886         }
7887
7888         /* Ensure st_size == 1000 */
7889         status = cli_posix_stat(cli1, fname, &sbuf);
7890         if (!NT_STATUS_IS_OK(status)) {
7891                 printf("stat failed (%s)\n", nt_errstr(status));
7892                 goto out;
7893         }
7894
7895         if (sbuf.st_ex_size != 1000) {
7896                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7897                 goto out;
7898         }
7899
7900         /* Ensure st_mode == 0600 */
7901         if ((sbuf.st_ex_mode & 07777) != 0600) {
7902                 printf("posix_open - bad permissions 0%o != 0600\n",
7903                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7904                 goto out;
7905         }
7906
7907         /* Test ftruncate - set file size back to zero. */
7908         status = cli_ftruncate(cli1, fnum1, 0);
7909         if (!NT_STATUS_IS_OK(status)) {
7910                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7911                 goto out;
7912         }
7913
7914         status = cli_close(cli1, fnum1);
7915         if (!NT_STATUS_IS_OK(status)) {
7916                 printf("close failed (%s)\n", nt_errstr(status));
7917                 goto out;
7918         }
7919
7920         /* Now open the file again for read only. */
7921         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7922         if (!NT_STATUS_IS_OK(status)) {
7923                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7924                 goto out;
7925         }
7926
7927         /* Now unlink while open. */
7928         status = cli_posix_unlink(cli1, fname);
7929         if (!NT_STATUS_IS_OK(status)) {
7930                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7931                 goto out;
7932         }
7933
7934         status = cli_close(cli1, fnum1);
7935         if (!NT_STATUS_IS_OK(status)) {
7936                 printf("close(2) failed (%s)\n", nt_errstr(status));
7937                 goto out;
7938         }
7939
7940         /* Ensure the file has gone. */
7941         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7942         if (NT_STATUS_IS_OK(status)) {
7943                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7944                 goto out;
7945         }
7946
7947         /* Create again to test open with O_TRUNC. */
7948         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7949         if (!NT_STATUS_IS_OK(status)) {
7950                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7951                 goto out;
7952         }
7953
7954         /* Test ftruncate - set file size. */
7955         status = cli_ftruncate(cli1, fnum1, 1000);
7956         if (!NT_STATUS_IS_OK(status)) {
7957                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7958                 goto out;
7959         }
7960
7961         /* Ensure st_size == 1000 */
7962         status = cli_posix_stat(cli1, fname, &sbuf);
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("stat failed (%s)\n", nt_errstr(status));
7965                 goto out;
7966         }
7967
7968         if (sbuf.st_ex_size != 1000) {
7969                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7970                 goto out;
7971         }
7972
7973         status = cli_close(cli1, fnum1);
7974         if (!NT_STATUS_IS_OK(status)) {
7975                 printf("close(2) failed (%s)\n", nt_errstr(status));
7976                 goto out;
7977         }
7978
7979         /* Re-open with O_TRUNC. */
7980         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7981         if (!NT_STATUS_IS_OK(status)) {
7982                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7983                 goto out;
7984         }
7985
7986         /* Ensure st_size == 0 */
7987         status = cli_posix_stat(cli1, fname, &sbuf);
7988         if (!NT_STATUS_IS_OK(status)) {
7989                 printf("stat failed (%s)\n", nt_errstr(status));
7990                 goto out;
7991         }
7992
7993         if (sbuf.st_ex_size != 0) {
7994                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7995                 goto out;
7996         }
7997
7998         status = cli_close(cli1, fnum1);
7999         if (!NT_STATUS_IS_OK(status)) {
8000                 printf("close failed (%s)\n", nt_errstr(status));
8001                 goto out;
8002         }
8003
8004         status = cli_posix_unlink(cli1, fname);
8005         if (!NT_STATUS_IS_OK(status)) {
8006                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8007                 goto out;
8008         }
8009
8010         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8011         if (!NT_STATUS_IS_OK(status)) {
8012                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8013                         dname, nt_errstr(status));
8014                 goto out;
8015         }
8016
8017         cli_close(cli1, fnum1);
8018
8019         /* What happens when we try and POSIX open a directory for write ? */
8020         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8021         if (NT_STATUS_IS_OK(status)) {
8022                 printf("POSIX open of directory %s succeeded, "
8023                        "should have failed.\n",
8024                        dname);
8025                 goto out;
8026         } else {
8027                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8028                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8029                         goto out;
8030                 }
8031         }
8032
8033         /* Create the file. */
8034         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8035                                 0600, &fnum1);
8036         if (!NT_STATUS_IS_OK(status)) {
8037                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8038                 goto out;
8039         }
8040
8041         /* Write some data into it. */
8042         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8043                               NULL);
8044         if (!NT_STATUS_IS_OK(status)) {
8045                 printf("cli_write failed: %s\n", nt_errstr(status));
8046                 goto out;
8047         }
8048
8049         cli_close(cli1, fnum1);
8050
8051         /* Now create a hardlink. */
8052         status = cli_posix_hardlink(cli1, fname, hname);
8053         if (!NT_STATUS_IS_OK(status)) {
8054                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8055                 goto out;
8056         }
8057
8058         /* Now create a symlink. */
8059         status = cli_posix_symlink(cli1, fname, sname);
8060         if (!NT_STATUS_IS_OK(status)) {
8061                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8062                 goto out;
8063         }
8064
8065         /* Open the hardlink for read. */
8066         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8067         if (!NT_STATUS_IS_OK(status)) {
8068                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8069                 goto out;
8070         }
8071
8072         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8073         if (!NT_STATUS_IS_OK(status)) {
8074                 printf("POSIX read of %s failed (%s)\n", hname,
8075                        nt_errstr(status));
8076                 goto out;
8077         } else if (nread != 10) {
8078                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8079                        hname, (unsigned long)nread, 10);
8080                 goto out;
8081         }
8082
8083         if (memcmp(buf, "TEST DATA\n", 10)) {
8084                 printf("invalid data read from hardlink\n");
8085                 goto out;
8086         }
8087
8088         /* Do a POSIX lock/unlock. */
8089         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8090         if (!NT_STATUS_IS_OK(status)) {
8091                 printf("POSIX lock failed %s\n", nt_errstr(status));
8092                 goto out;
8093         }
8094
8095         /* Punch a hole in the locked area. */
8096         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8097         if (!NT_STATUS_IS_OK(status)) {
8098                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8099                 goto out;
8100         }
8101
8102         cli_close(cli1, fnum1);
8103
8104         /* Open the symlink for read - this should fail. A POSIX
8105            client should not be doing opens on a symlink. */
8106         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8107         if (NT_STATUS_IS_OK(status)) {
8108                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8109                 goto out;
8110         }
8111         ok = check_both_error(
8112                 __LINE__, status, ERRDOS, ERRbadpath,
8113                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8114         if (!ok) {
8115                 printf("POSIX open of %s should have failed "
8116                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8117                        "failed with %s instead.\n",
8118                        sname, nt_errstr(status));
8119                 goto out;
8120         }
8121
8122         status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8123         if (!NT_STATUS_IS_OK(status)) {
8124                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8125                 goto out;
8126         }
8127
8128         if (strcmp(target, fname) != 0) {
8129                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8130                         sname, fname, target);
8131                 goto out;
8132         }
8133
8134         status = cli_posix_rmdir(cli1, dname);
8135         if (!NT_STATUS_IS_OK(status)) {
8136                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8137                 goto out;
8138         }
8139
8140         /* Check directory opens with a specific permission. */
8141         status = cli_posix_mkdir(cli1, dname, 0700);
8142         if (!NT_STATUS_IS_OK(status)) {
8143                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8144                 goto out;
8145         }
8146
8147         /* Ensure st_mode == 0700 */
8148         status = cli_posix_stat(cli1, dname, &sbuf);
8149         if (!NT_STATUS_IS_OK(status)) {
8150                 printf("stat failed (%s)\n", nt_errstr(status));
8151                 goto out;
8152         }
8153
8154         if ((sbuf.st_ex_mode & 07777) != 0700) {
8155                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8156                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8157                 goto out;
8158         }
8159
8160         /*
8161          * Now create a Windows file, and attempt a POSIX unlink.
8162          * This should fail with a sharing violation but due to:
8163          *
8164          * [Bug 9571] Unlink after open causes smbd to panic
8165          *
8166          * ensure we've fixed the lock ordering violation.
8167          */
8168
8169         status = cli_ntcreate(cli1, fname_windows, 0,
8170                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8171                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8172                         FILE_CREATE,
8173                         0x0, 0x0, &fnum2, NULL);
8174         if (!NT_STATUS_IS_OK(status)) {
8175                 printf("Windows create of %s failed (%s)\n", fname_windows,
8176                         nt_errstr(status));
8177                 goto out;
8178         }
8179
8180         /* Now try posix_unlink. */
8181         status = cli_posix_unlink(cli1, fname_windows);
8182         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8183                 printf("POSIX unlink of %s should fail "
8184                         "with NT_STATUS_SHARING_VIOLATION "
8185                         "got %s instead !\n",
8186                         fname_windows,
8187                         nt_errstr(status));
8188                 goto out;
8189         }
8190
8191         cli_close(cli1, fnum2);
8192
8193         printf("Simple POSIX open test passed\n");
8194         correct = true;
8195
8196   out:
8197
8198         if (fnum1 != (uint16_t)-1) {
8199                 cli_close(cli1, fnum1);
8200                 fnum1 = (uint16_t)-1;
8201         }
8202
8203         if (fnum2 != (uint16_t)-1) {
8204                 cli_close(cli1, fnum2);
8205                 fnum2 = (uint16_t)-1;
8206         }
8207
8208         cli_setatr(cli1, sname, 0, 0);
8209         cli_posix_unlink(cli1, sname);
8210         cli_setatr(cli1, hname, 0, 0);
8211         cli_posix_unlink(cli1, hname);
8212         cli_setatr(cli1, fname, 0, 0);
8213         cli_posix_unlink(cli1, fname);
8214         cli_setatr(cli1, dname, 0, 0);
8215         cli_posix_rmdir(cli1, dname);
8216         cli_setatr(cli1, fname_windows, 0, 0);
8217         cli_posix_unlink(cli1, fname_windows);
8218
8219         if (!torture_close_connection(cli1)) {
8220                 correct = false;
8221         }
8222
8223         return correct;
8224 }
8225
8226 /*
8227   Test POSIX and Windows ACLs are rejected on symlinks.
8228  */
8229 static bool run_acl_symlink_test(int dummy)
8230 {
8231         static struct cli_state *cli;
8232         const char *fname = "posix_file";
8233         const char *sname = "posix_symlink";
8234         uint16_t fnum = (uint16_t)-1;
8235         bool correct = false;
8236         NTSTATUS status;
8237         char *posix_acl = NULL;
8238         size_t posix_acl_len = 0;
8239         char *posix_acl_sym = NULL;
8240         size_t posix_acl_len_sym = 0;
8241         struct security_descriptor *sd = NULL;
8242         TALLOC_CTX *frame = NULL;
8243
8244         frame = talloc_stackframe();
8245
8246         printf("Starting acl symlink test\n");
8247
8248         if (!torture_open_connection(&cli, 0)) {
8249                 TALLOC_FREE(frame);
8250                 return false;
8251         }
8252
8253         smbXcli_conn_set_sockopt(cli->conn, sockops);
8254
8255         status = torture_setup_unix_extensions(cli);
8256         if (!NT_STATUS_IS_OK(status)) {
8257                 TALLOC_FREE(frame);
8258                 return false;
8259         }
8260
8261         cli_setatr(cli, fname, 0, 0);
8262         cli_posix_unlink(cli, fname);
8263         cli_setatr(cli, sname, 0, 0);
8264         cli_posix_unlink(cli, sname);
8265
8266         status = cli_ntcreate(cli,
8267                         fname,
8268                         0,
8269                         READ_CONTROL_ACCESS,
8270                         0,
8271                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8272                         FILE_CREATE,
8273                         0x0,
8274                         0x0,
8275                         &fnum,
8276                         NULL);
8277
8278         if (!NT_STATUS_IS_OK(status)) {
8279                 printf("cli_ntcreate of %s failed (%s)\n",
8280                         fname,
8281                         nt_errstr(status));
8282                 goto out;
8283         }
8284
8285         /* Get the Windows ACL on the file. */
8286         status = cli_query_secdesc(cli,
8287                                 fnum,
8288                                 frame,
8289                                 &sd);
8290         if (!NT_STATUS_IS_OK(status)) {
8291                 printf("cli_query_secdesc failed (%s)\n",
8292                         nt_errstr(status));
8293                 goto out;
8294         }
8295
8296         /* Get the POSIX ACL on the file. */
8297         status = cli_posix_getacl(cli,
8298                                 fname,
8299                                 frame,
8300                                 &posix_acl_len,
8301                                 &posix_acl);
8302
8303         if (!NT_STATUS_IS_OK(status)) {
8304                 printf("cli_posix_getacl failed (%s)\n",
8305                         nt_errstr(status));
8306                 goto out;
8307         }
8308
8309         status = cli_close(cli, fnum);
8310         if (!NT_STATUS_IS_OK(status)) {
8311                 printf("close failed (%s)\n", nt_errstr(status));
8312                 goto out;
8313         }
8314         fnum = (uint16_t)-1;
8315
8316         /* Now create a symlink. */
8317         status = cli_posix_symlink(cli, fname, sname);
8318         if (!NT_STATUS_IS_OK(status)) {
8319                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8320                         sname,
8321                         fname,
8322                         nt_errstr(status));
8323                 goto out;
8324         }
8325
8326         /* Open a handle on the symlink for SD set/get should fail. */
8327         status = cli_ntcreate(cli,
8328                         sname,
8329                         0,
8330                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8331                         0,
8332                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8333                         FILE_OPEN,
8334                         0x0,
8335                         0x0,
8336                         &fnum,
8337                         NULL);
8338
8339         if (NT_STATUS_IS_OK(status)) {
8340                 printf("Symlink open for getsd/setsd of %s "
8341                         "succeeded (should fail)\n",
8342                         sname);
8343                 goto out;
8344         }
8345
8346         /* Try a stat-open on the symlink, should also fail. */
8347         status = cli_ntcreate(cli,
8348                         sname,
8349                         0,
8350                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8351                         0,
8352                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8353                         FILE_OPEN,
8354                         0x0,
8355                         0x0,
8356                         &fnum,
8357                         NULL);
8358
8359         if (NT_STATUS_IS_OK(status)) {
8360                 printf("Stat-open of symlink succeeded (should fail)\n");
8361                 goto out;
8362         }
8363
8364         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8365         status = cli_posix_getacl(cli,
8366                                 sname,
8367                                 frame,
8368                                 &posix_acl_len_sym,
8369                                 &posix_acl_sym);
8370
8371         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8372                 printf("cli_posix_getacl on a symlink gave %s. "
8373                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8374                         nt_errstr(status));
8375                 goto out;
8376         }
8377
8378         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8379         status = cli_posix_setacl(cli,
8380                                 sname,
8381                                 posix_acl,
8382                                 posix_acl_len);
8383
8384         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8385                 printf("cli_posix_setacl on a symlink gave %s. "
8386                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8387                         nt_errstr(status));
8388                 goto out;
8389         }
8390
8391         printf("ACL symlink test passed\n");
8392         correct = true;
8393
8394   out:
8395
8396         if (fnum != (uint16_t)-1) {
8397                 cli_close(cli, fnum);
8398                 fnum = (uint16_t)-1;
8399         }
8400
8401         cli_setatr(cli, sname, 0, 0);
8402         cli_posix_unlink(cli, sname);
8403         cli_setatr(cli, fname, 0, 0);
8404         cli_posix_unlink(cli, fname);
8405
8406         if (!torture_close_connection(cli)) {
8407                 correct = false;
8408         }
8409
8410         TALLOC_FREE(frame);
8411         return correct;
8412 }
8413
8414 /*
8415   Test POSIX can delete a file containing streams.
8416  */
8417 static bool run_posix_stream_delete(int dummy)
8418 {
8419         struct cli_state *cli1 = NULL;
8420         struct cli_state *cli2 = NULL;
8421         const char *fname = "streamfile";
8422         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8423         uint16_t fnum1 = (uint16_t)-1;
8424         bool correct = false;
8425         NTSTATUS status;
8426         TALLOC_CTX *frame = NULL;
8427
8428         frame = talloc_stackframe();
8429
8430         printf("Starting POSIX stream delete test\n");
8431
8432         if (!torture_open_connection(&cli1, 0) ||
8433                         !torture_open_connection(&cli2, 1)) {
8434                 TALLOC_FREE(frame);
8435                 return false;
8436         }
8437
8438         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8439         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8440
8441         status = torture_setup_unix_extensions(cli2);
8442         if (!NT_STATUS_IS_OK(status)) {
8443                 goto out;
8444         }
8445
8446         cli_setatr(cli1, fname, 0, 0);
8447         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8448
8449         /* Create the file. */
8450         status = cli_ntcreate(cli1,
8451                         fname,
8452                         0,
8453                         READ_CONTROL_ACCESS,
8454                         0,
8455                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8456                         FILE_CREATE,
8457                         0x0,
8458                         0x0,
8459                         &fnum1,
8460                         NULL);
8461
8462         if (!NT_STATUS_IS_OK(status)) {
8463                 printf("cli_ntcreate of %s failed (%s)\n",
8464                         fname,
8465                         nt_errstr(status));
8466                 goto out;
8467         }
8468
8469         status = cli_close(cli1, fnum1);
8470         if (!NT_STATUS_IS_OK(status)) {
8471                 printf("cli_close of %s failed (%s)\n",
8472                         fname,
8473                         nt_errstr(status));
8474                 goto out;
8475         }
8476         fnum1 = (uint16_t)-1;
8477
8478         /* Now create the stream. */
8479         status = cli_ntcreate(cli1,
8480                         stream_fname,
8481                         0,
8482                         FILE_WRITE_DATA,
8483                         0,
8484                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8485                         FILE_CREATE,
8486                         0x0,
8487                         0x0,
8488                         &fnum1,
8489                         NULL);
8490
8491         if (!NT_STATUS_IS_OK(status)) {
8492                 printf("cli_ntcreate of %s failed (%s)\n",
8493                         stream_fname,
8494                         nt_errstr(status));
8495                 goto out;
8496         }
8497
8498         /* Leave the stream handle open... */
8499
8500         /* POSIX unlink should fail. */
8501         status = cli_posix_unlink(cli2, fname);
8502         if (NT_STATUS_IS_OK(status)) {
8503                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8504                         fname);
8505                 goto out;
8506         }
8507
8508         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8509                 printf("cli_posix_unlink of %s failed with (%s) "
8510                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8511                         fname,
8512                         nt_errstr(status));
8513                 goto out;
8514         }
8515
8516         /* Close the stream handle. */
8517         status = cli_close(cli1, fnum1);
8518         if (!NT_STATUS_IS_OK(status)) {
8519                 printf("cli_close of %s failed (%s)\n",
8520                         stream_fname,
8521                         nt_errstr(status));
8522                 goto out;
8523         }
8524         fnum1 = (uint16_t)-1;
8525
8526         /* POSIX unlink after stream handle closed should succeed. */
8527         status = cli_posix_unlink(cli2, fname);
8528         if (!NT_STATUS_IS_OK(status)) {
8529                 printf("cli_posix_unlink of %s failed (%s)\n",
8530                         fname,
8531                         nt_errstr(status));
8532                 goto out;
8533         }
8534
8535         printf("POSIX stream delete test passed\n");
8536         correct = true;
8537
8538   out:
8539
8540         if (fnum1 != (uint16_t)-1) {
8541                 cli_close(cli1, fnum1);
8542                 fnum1 = (uint16_t)-1;
8543         }
8544
8545         cli_setatr(cli1, fname, 0, 0);
8546         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8547
8548         if (!torture_close_connection(cli1)) {
8549                 correct = false;
8550         }
8551         if (!torture_close_connection(cli2)) {
8552                 correct = false;
8553         }
8554
8555         TALLOC_FREE(frame);
8556         return correct;
8557 }
8558
8559 /*
8560   Test setting EA's are rejected on symlinks.
8561  */
8562 static bool run_ea_symlink_test(int dummy)
8563 {
8564         static struct cli_state *cli;
8565         const char *fname = "posix_file_ea";
8566         const char *sname = "posix_symlink_ea";
8567         const char *ea_name = "testea_name";
8568         const char *ea_value = "testea_value";
8569         uint16_t fnum = (uint16_t)-1;
8570         bool correct = false;
8571         NTSTATUS status;
8572         size_t i, num_eas;
8573         struct ea_struct *eas = NULL;
8574         TALLOC_CTX *frame = NULL;
8575
8576         frame = talloc_stackframe();
8577
8578         printf("Starting EA symlink test\n");
8579
8580         if (!torture_open_connection(&cli, 0)) {
8581                 TALLOC_FREE(frame);
8582                 return false;
8583         }
8584
8585         smbXcli_conn_set_sockopt(cli->conn, sockops);
8586
8587         status = torture_setup_unix_extensions(cli);
8588         if (!NT_STATUS_IS_OK(status)) {
8589                 TALLOC_FREE(frame);
8590                 return false;
8591         }
8592
8593         cli_setatr(cli, fname, 0, 0);
8594         cli_posix_unlink(cli, fname);
8595         cli_setatr(cli, sname, 0, 0);
8596         cli_posix_unlink(cli, sname);
8597
8598         status = cli_ntcreate(cli,
8599                         fname,
8600                         0,
8601                         READ_CONTROL_ACCESS,
8602                         0,
8603                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8604                         FILE_CREATE,
8605                         0x0,
8606                         0x0,
8607                         &fnum,
8608                         NULL);
8609
8610         if (!NT_STATUS_IS_OK(status)) {
8611                 printf("cli_ntcreate of %s failed (%s)\n",
8612                         fname,
8613                         nt_errstr(status));
8614                 goto out;
8615         }
8616
8617         status = cli_close(cli, fnum);
8618         if (!NT_STATUS_IS_OK(status)) {
8619                 printf("close failed (%s)\n",
8620                         nt_errstr(status));
8621                 goto out;
8622         }
8623         fnum = (uint16_t)-1;
8624
8625         /* Set an EA on the path. */
8626         status = cli_set_ea_path(cli,
8627                                 fname,
8628                                 ea_name,
8629                                 ea_value,
8630                                 strlen(ea_value)+1);
8631
8632         if (!NT_STATUS_IS_OK(status)) {
8633                 printf("cli_set_ea_path failed (%s)\n",
8634                         nt_errstr(status));
8635                 goto out;
8636         }
8637
8638         /* Now create a symlink. */
8639         status = cli_posix_symlink(cli, fname, sname);
8640         if (!NT_STATUS_IS_OK(status)) {
8641                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8642                         sname,
8643                         fname,
8644                         nt_errstr(status));
8645                 goto out;
8646         }
8647
8648         /* Get the EA list on the path. Should return value set. */
8649         status = cli_get_ea_list_path(cli,
8650                                 fname,
8651                                 frame,
8652                                 &num_eas,
8653                                 &eas);
8654
8655         if (!NT_STATUS_IS_OK(status)) {
8656                 printf("cli_get_ea_list_path failed (%s)\n",
8657                         nt_errstr(status));
8658                 goto out;
8659         }
8660
8661         /* Ensure the EA we set is there. */
8662         for (i=0; i<num_eas; i++) {
8663                 if (strcmp(eas[i].name, ea_name) == 0 &&
8664                                 eas[i].value.length == strlen(ea_value)+1 &&
8665                                 memcmp(eas[i].value.data,
8666                                         ea_value,
8667                                         eas[i].value.length) == 0) {
8668                         break;
8669                 }
8670         }
8671
8672         if (i == num_eas) {
8673                 printf("Didn't find EA on pathname %s\n",
8674                         fname);
8675                 goto out;
8676         }
8677
8678         num_eas = 0;
8679         TALLOC_FREE(eas);
8680
8681         /* Get the EA list on the symlink. Should return empty list. */
8682         status = cli_get_ea_list_path(cli,
8683                                 sname,
8684                                 frame,
8685                                 &num_eas,
8686                                 &eas);
8687
8688         if (!NT_STATUS_IS_OK(status)) {
8689                 printf("cli_get_ea_list_path failed (%s)\n",
8690                         nt_errstr(status));
8691                 goto out;
8692         }
8693
8694         if (num_eas != 0) {
8695                 printf("cli_get_ea_list_path failed (%s)\n",
8696                         nt_errstr(status));
8697                 goto out;
8698         }
8699
8700         /* Set an EA on the symlink. Should fail. */
8701         status = cli_set_ea_path(cli,
8702                                 sname,
8703                                 ea_name,
8704                                 ea_value,
8705                                 strlen(ea_value)+1);
8706
8707         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8708                 printf("cli_set_ea_path on a symlink gave %s. "
8709                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8710                         nt_errstr(status));
8711                 goto out;
8712         }
8713
8714         printf("EA symlink test passed\n");
8715         correct = true;
8716
8717   out:
8718
8719         if (fnum != (uint16_t)-1) {
8720                 cli_close(cli, fnum);
8721                 fnum = (uint16_t)-1;
8722         }
8723
8724         cli_setatr(cli, sname, 0, 0);
8725         cli_posix_unlink(cli, sname);
8726         cli_setatr(cli, fname, 0, 0);
8727         cli_posix_unlink(cli, fname);
8728
8729         if (!torture_close_connection(cli)) {
8730                 correct = false;
8731         }
8732
8733         TALLOC_FREE(frame);
8734         return correct;
8735 }
8736
8737 /*
8738   Test POSIX locks are OFD-locks.
8739  */
8740 static bool run_posix_ofd_lock_test(int dummy)
8741 {
8742         static struct cli_state *cli;
8743         const char *fname = "posix_file";
8744         uint16_t fnum1 = (uint16_t)-1;
8745         uint16_t fnum2 = (uint16_t)-1;
8746         bool correct = false;
8747         NTSTATUS status;
8748         TALLOC_CTX *frame = NULL;
8749
8750         frame = talloc_stackframe();
8751
8752         printf("Starting POSIX ofd-lock test\n");
8753
8754         if (!torture_open_connection(&cli, 0)) {
8755                 TALLOC_FREE(frame);
8756                 return false;
8757         }
8758
8759         smbXcli_conn_set_sockopt(cli->conn, sockops);
8760
8761         status = torture_setup_unix_extensions(cli);
8762         if (!NT_STATUS_IS_OK(status)) {
8763                 TALLOC_FREE(frame);
8764                 return false;
8765         }
8766
8767         cli_setatr(cli, fname, 0, 0);
8768         cli_posix_unlink(cli, fname);
8769
8770         /* Open the file twice. */
8771         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8772                                 0600, &fnum1);
8773         if (!NT_STATUS_IS_OK(status)) {
8774                 printf("First POSIX open of %s failed\n", fname);
8775                 goto out;
8776         }
8777
8778         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8779         if (!NT_STATUS_IS_OK(status)) {
8780                 printf("First POSIX open of %s failed\n", fname);
8781                 goto out;
8782         }
8783
8784         /* Set a 0-50 lock on fnum1. */
8785         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8786         if (!NT_STATUS_IS_OK(status)) {
8787                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8788                 goto out;
8789         }
8790
8791         /* Set a 60-100 lock on fnum2. */
8792         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8793         if (!NT_STATUS_IS_OK(status)) {
8794                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8795                 goto out;
8796         }
8797
8798         /* close fnum1 - 0-50 lock should go away. */
8799         status = cli_close(cli, fnum1);
8800         if (!NT_STATUS_IS_OK(status)) {
8801                 printf("close failed (%s)\n",
8802                         nt_errstr(status));
8803                 goto out;
8804         }
8805         fnum1 = (uint16_t)-1;
8806
8807         /* Change the lock context. */
8808         cli_setpid(cli, cli_getpid(cli) + 1);
8809
8810         /* Re-open fnum1. */
8811         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8812         if (!NT_STATUS_IS_OK(status)) {
8813                 printf("Third POSIX open of %s failed\n", fname);
8814                 goto out;
8815         }
8816
8817         /* 60-100 lock should still be there. */
8818         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8819         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8820                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8821                 goto out;
8822         }
8823
8824         /* 0-50 lock should be gone. */
8825         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8826         if (!NT_STATUS_IS_OK(status)) {
8827                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8828                 goto out;
8829         }
8830
8831         printf("POSIX OFD lock test passed\n");
8832         correct = true;
8833
8834   out:
8835
8836         if (fnum1 != (uint16_t)-1) {
8837                 cli_close(cli, fnum1);
8838                 fnum1 = (uint16_t)-1;
8839         }
8840         if (fnum2 != (uint16_t)-1) {
8841                 cli_close(cli, fnum2);
8842                 fnum2 = (uint16_t)-1;
8843         }
8844
8845         cli_setatr(cli, fname, 0, 0);
8846         cli_posix_unlink(cli, fname);
8847
8848         if (!torture_close_connection(cli)) {
8849                 correct = false;
8850         }
8851
8852         TALLOC_FREE(frame);
8853         return correct;
8854 }
8855
8856 struct posix_blocking_state {
8857         struct tevent_context *ev;
8858         struct cli_state *cli1;
8859         uint16_t fnum1;
8860         struct cli_state *cli2;
8861         uint16_t fnum2;
8862         bool gotblocked;
8863         bool gotecho;
8864 };
8865
8866 static void posix_blocking_locked(struct tevent_req *subreq);
8867 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8868 static void posix_blocking_gotecho(struct tevent_req *subreq);
8869 static void posix_blocking_unlocked(struct tevent_req *subreq);
8870
8871 static struct tevent_req *posix_blocking_send(
8872         TALLOC_CTX *mem_ctx,
8873         struct tevent_context *ev,
8874         struct cli_state *cli1,
8875         uint16_t fnum1,
8876         struct cli_state *cli2,
8877         uint16_t fnum2)
8878 {
8879         struct tevent_req *req = NULL, *subreq = NULL;
8880         struct posix_blocking_state *state = NULL;
8881
8882         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8883         if (req == NULL) {
8884                 return NULL;
8885         }
8886         state->ev = ev;
8887         state->cli1 = cli1;
8888         state->fnum1 = fnum1;
8889         state->cli2 = cli2;
8890         state->fnum2 = fnum2;
8891
8892         subreq = cli_posix_lock_send(
8893                 state,
8894                 state->ev,
8895                 state->cli1,
8896                 state->fnum1,
8897                 0,
8898                 1,
8899                 false,
8900                 WRITE_LOCK);
8901         if (tevent_req_nomem(subreq, req)) {
8902                 return tevent_req_post(req, ev);
8903         }
8904         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8905         return req;
8906 }
8907
8908 static void posix_blocking_locked(struct tevent_req *subreq)
8909 {
8910         struct tevent_req *req = tevent_req_callback_data(
8911                 subreq, struct tevent_req);
8912         struct posix_blocking_state *state = tevent_req_data(
8913                 req, struct posix_blocking_state);
8914         NTSTATUS status;
8915
8916         status = cli_posix_lock_recv(subreq);
8917         TALLOC_FREE(subreq);
8918         if (tevent_req_nterror(req, status)) {
8919                 return;
8920         }
8921
8922         subreq = cli_posix_lock_send(
8923                 state,
8924                 state->ev,
8925                 state->cli2,
8926                 state->fnum2,
8927                 0,
8928                 1,
8929                 true,
8930                 WRITE_LOCK);
8931         if (tevent_req_nomem(subreq, req)) {
8932                 return;
8933         }
8934         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8935
8936         /* Make sure the blocking request is delivered */
8937         subreq = cli_echo_send(
8938                 state,
8939                 state->ev,
8940                 state->cli2,
8941                 1,
8942                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8943         if (tevent_req_nomem(subreq, req)) {
8944                 return;
8945         }
8946         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8947 }
8948
8949 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8950 {
8951         struct tevent_req *req = tevent_req_callback_data(
8952                 subreq, struct tevent_req);
8953         struct posix_blocking_state *state = tevent_req_data(
8954                 req, struct posix_blocking_state);
8955         NTSTATUS status;
8956
8957         status = cli_posix_lock_recv(subreq);
8958         TALLOC_FREE(subreq);
8959         if (tevent_req_nterror(req, status)) {
8960                 return;
8961         }
8962         if (!state->gotecho) {
8963                 printf("blocked req got through before echo\n");
8964                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8965                 return;
8966         }
8967         tevent_req_done(req);
8968 }
8969
8970 static void posix_blocking_gotecho(struct tevent_req *subreq)
8971 {
8972         struct tevent_req *req = tevent_req_callback_data(
8973                 subreq, struct tevent_req);
8974         struct posix_blocking_state *state = tevent_req_data(
8975                 req, struct posix_blocking_state);
8976         NTSTATUS status;
8977
8978         status = cli_echo_recv(subreq);
8979         TALLOC_FREE(subreq);
8980         if (tevent_req_nterror(req, status)) {
8981                 return;
8982         }
8983         if (state->gotblocked) {
8984                 printf("blocked req got through before echo\n");
8985                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8986                 return;
8987         }
8988         state->gotecho = true;
8989
8990         subreq = cli_posix_lock_send(
8991                 state,
8992                 state->ev,
8993                 state->cli1,
8994                 state->fnum1,
8995                 0,
8996                 1,
8997                 false,
8998                 UNLOCK_LOCK);
8999         if (tevent_req_nomem(subreq, req)) {
9000                 return;
9001         }
9002         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9003 }
9004
9005 static void posix_blocking_unlocked(struct tevent_req *subreq)
9006 {
9007         struct tevent_req *req = tevent_req_callback_data(
9008                 subreq, struct tevent_req);
9009         NTSTATUS status;
9010
9011         status = cli_posix_lock_recv(subreq);
9012         TALLOC_FREE(subreq);
9013         if (tevent_req_nterror(req, status)) {
9014                 return;
9015         }
9016         /* tevent_req_done in posix_blocking_gotlocked */
9017 }
9018
9019 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9020 {
9021         return tevent_req_simple_recv_ntstatus(req);
9022 }
9023
9024 static bool run_posix_blocking_lock(int dummy)
9025 {
9026         struct tevent_context *ev = NULL;
9027         struct cli_state *cli1 = NULL, *cli2 = NULL;
9028         const char *fname = "posix_blocking";
9029         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9030         struct tevent_req *req = NULL;
9031         NTSTATUS status;
9032         bool ret = false;
9033         bool ok;
9034
9035         printf("Starting posix blocking lock test\n");
9036
9037         ev = samba_tevent_context_init(NULL);
9038         if (ev == NULL) {
9039                 return false;
9040         }
9041
9042         ok = torture_open_connection(&cli1, 0);
9043         if (!ok) {
9044                 goto fail;
9045         }
9046         ok = torture_open_connection(&cli2, 0);
9047         if (!ok) {
9048                 goto fail;
9049         }
9050
9051         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9052
9053         status = torture_setup_unix_extensions(cli1);
9054         if (!NT_STATUS_IS_OK(status)) {
9055                 return false;
9056         }
9057
9058         status = torture_setup_unix_extensions(cli2);
9059         if (!NT_STATUS_IS_OK(status)) {
9060                 return false;
9061         }
9062
9063         cli_setatr(cli1, fname, 0, 0);
9064         cli_posix_unlink(cli1, fname);
9065
9066         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9067                                 0600, &fnum1);
9068         if (!NT_STATUS_IS_OK(status)) {
9069                 printf("First POSIX open of %s failed: %s\n",
9070                        fname,
9071                        nt_errstr(status));
9072                 goto fail;
9073         }
9074
9075         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9076         if (!NT_STATUS_IS_OK(status)) {
9077                 printf("Second POSIX open of %s failed: %s\n",
9078                        fname,
9079                        nt_errstr(status));
9080                 goto fail;
9081         }
9082
9083         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9084         if (req == NULL) {
9085                 printf("cli_posix_blocking failed\n");
9086                 goto fail;
9087         }
9088
9089         ok = tevent_req_poll_ntstatus(req, ev, &status);
9090         if (!ok) {
9091                 printf("tevent_req_poll_ntstatus failed: %s\n",
9092                        nt_errstr(status));
9093                 goto fail;
9094         }
9095         status = posix_blocking_recv(req);
9096         TALLOC_FREE(req);
9097         if (!NT_STATUS_IS_OK(status)) {
9098                 printf("posix_blocking_recv returned %s\n",
9099                        nt_errstr(status));
9100                 goto fail;
9101         }
9102
9103         ret = true;
9104 fail:
9105
9106         if (fnum1 != UINT16_MAX) {
9107                 cli_close(cli1, fnum1);
9108                 fnum1 = UINT16_MAX;
9109         }
9110         if (fnum2 != UINT16_MAX) {
9111                 cli_close(cli2, fnum2);
9112                 fnum2 = UINT16_MAX;
9113         }
9114
9115         if (cli1 != NULL) {
9116                 cli_setatr(cli1, fname, 0, 0);
9117                 cli_posix_unlink(cli1, fname);
9118         }
9119
9120         ok = true;
9121
9122         if (cli1 != NULL) {
9123                 ok &= torture_close_connection(cli1);
9124                 cli1 = NULL;
9125         }
9126         if (cli2 != NULL) {
9127                 ok &= torture_close_connection(cli2);
9128                 cli2 = NULL;
9129         }
9130
9131         if (!ok) {
9132                 ret = false;
9133         }
9134         TALLOC_FREE(ev);
9135         return ret;
9136 }
9137
9138 /*
9139   Test POSIX mkdir is case-sensitive.
9140  */
9141 static bool run_posix_mkdir_test(int dummy)
9142 {
9143         static struct cli_state *cli;
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         const char *fname_Foo = "POSIX_Foo";
9148         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9149         const char *fname_Foo_foo = "POSIX_Foo/foo";
9150         bool correct = false;
9151         NTSTATUS status;
9152         TALLOC_CTX *frame = NULL;
9153         uint16_t fnum = (uint16_t)-1;
9154
9155         frame = talloc_stackframe();
9156
9157         printf("Starting POSIX mkdir test\n");
9158
9159         if (!torture_open_connection(&cli, 0)) {
9160                 TALLOC_FREE(frame);
9161                 return false;
9162         }
9163
9164         smbXcli_conn_set_sockopt(cli->conn, sockops);
9165
9166         status = torture_setup_unix_extensions(cli);
9167         if (!NT_STATUS_IS_OK(status)) {
9168                 TALLOC_FREE(frame);
9169                 return false;
9170         }
9171
9172         cli_posix_rmdir(cli, fname_foo_foo);
9173         cli_posix_rmdir(cli, fname_foo_Foo);
9174         cli_posix_rmdir(cli, fname_foo);
9175
9176         cli_posix_rmdir(cli, fname_Foo_foo);
9177         cli_posix_rmdir(cli, fname_Foo_Foo);
9178         cli_posix_rmdir(cli, fname_Foo);
9179
9180         /*
9181          * Create a file POSIX_foo then try
9182          * and use it in a directory path by
9183          * doing mkdir POSIX_foo/bar.
9184          * The mkdir should fail with
9185          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9186          */
9187
9188         status = cli_posix_open(cli,
9189                         fname_foo,
9190                         O_RDWR|O_CREAT,
9191                         0666,
9192                         &fnum);
9193         if (!NT_STATUS_IS_OK(status)) {
9194                 printf("cli_posix_open of %s failed error %s\n",
9195                         fname_foo,
9196                         nt_errstr(status));
9197                 goto out;
9198         }
9199
9200         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9201         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9202                 printf("cli_posix_mkdir of %s should fail with "
9203                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9204                         "%s instead\n",
9205                         fname_foo_foo,
9206                         nt_errstr(status));
9207                 goto out;
9208         }
9209
9210         status = cli_close(cli, fnum);
9211         if (!NT_STATUS_IS_OK(status)) {
9212                 printf("cli_close failed %s\n", nt_errstr(status));
9213                 goto out;
9214         }
9215         fnum = (uint16_t)-1;
9216
9217         status = cli_posix_unlink(cli, fname_foo);
9218         if (!NT_STATUS_IS_OK(status)) {
9219                 printf("cli_posix_unlink of %s failed error %s\n",
9220                         fname_foo,
9221                         nt_errstr(status));
9222                 goto out;
9223         }
9224
9225         /*
9226          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9227          * posix_open, posix_unlink, on
9228          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9229          * not silently create POSIX_foo/foo.
9230          */
9231
9232         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9233         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9234                 printf("cli_posix_mkdir of %s should fail with "
9235                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9236                         "%s instead\n",
9237                         fname_foo_foo,
9238                         nt_errstr(status));
9239                 goto out;
9240         }
9241
9242         status = cli_posix_rmdir(cli, fname_foo_foo);
9243         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9244                 printf("cli_posix_rmdir of %s should fail with "
9245                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9246                         "%s instead\n",
9247                         fname_foo_foo,
9248                         nt_errstr(status));
9249                 goto out;
9250         }
9251
9252         status = cli_posix_open(cli,
9253                         fname_foo_foo,
9254                         O_RDWR|O_CREAT,
9255                         0666,
9256                         &fnum);
9257         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9258                 printf("cli_posix_open of %s should fail with "
9259                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9260                         "%s instead\n",
9261                         fname_foo_foo,
9262                         nt_errstr(status));
9263                 goto out;
9264         }
9265
9266         status = cli_posix_unlink(cli, fname_foo_foo);
9267         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9268                 printf("cli_posix_unlink of %s should fail with "
9269                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9270                         "%s instead\n",
9271                         fname_foo_foo,
9272                         nt_errstr(status));
9273                 goto out;
9274         }
9275
9276         status = cli_posix_mkdir(cli, fname_foo, 0777);
9277         if (!NT_STATUS_IS_OK(status)) {
9278                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9279                 goto out;
9280         }
9281
9282         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9283         if (!NT_STATUS_IS_OK(status)) {
9284                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9285                 goto out;
9286         }
9287
9288         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9289         if (!NT_STATUS_IS_OK(status)) {
9290                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9291                 goto out;
9292         }
9293
9294         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9295         if (!NT_STATUS_IS_OK(status)) {
9296                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9297                 goto out;
9298         }
9299
9300         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9301         if (!NT_STATUS_IS_OK(status)) {
9302                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9303                 goto out;
9304         }
9305
9306         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9307         if (!NT_STATUS_IS_OK(status)) {
9308                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9309                 goto out;
9310         }
9311
9312         printf("POSIX mkdir test passed\n");
9313         correct = true;
9314
9315   out:
9316
9317         if (fnum != (uint16_t)-1) {
9318                 cli_close(cli, fnum);
9319                 fnum = (uint16_t)-1;
9320         }
9321
9322         cli_posix_rmdir(cli, fname_foo_foo);
9323         cli_posix_rmdir(cli, fname_foo_Foo);
9324         cli_posix_rmdir(cli, fname_foo);
9325
9326         cli_posix_rmdir(cli, fname_Foo_foo);
9327         cli_posix_rmdir(cli, fname_Foo_Foo);
9328         cli_posix_rmdir(cli, fname_Foo);
9329
9330         if (!torture_close_connection(cli)) {
9331                 correct = false;
9332         }
9333
9334         TALLOC_FREE(frame);
9335         return correct;
9336 }
9337
9338 struct posix_acl_oplock_state {
9339         struct tevent_context *ev;
9340         struct cli_state *cli;
9341         bool *got_break;
9342         bool *acl_ret;
9343         NTSTATUS status;
9344 };
9345
9346 static void posix_acl_oplock_got_break(struct tevent_req *req)
9347 {
9348         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9349                 req, struct posix_acl_oplock_state);
9350         uint16_t fnum;
9351         uint8_t level;
9352         NTSTATUS status;
9353
9354         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9355         TALLOC_FREE(req);
9356         if (!NT_STATUS_IS_OK(status)) {
9357                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9358                        nt_errstr(status));
9359                 return;
9360         }
9361         *state->got_break = true;
9362
9363         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9364                                   NO_OPLOCK);
9365         if (req == NULL) {
9366                 printf("cli_oplock_ack_send failed\n");
9367                 return;
9368         }
9369 }
9370
9371 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9372 {
9373         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9374                 req, struct posix_acl_oplock_state);
9375         size_t ret_size = 0;
9376         char *ret_data = NULL;
9377
9378         state->status = cli_posix_getacl_recv(req,
9379                         state,
9380                         &ret_size,
9381                         &ret_data);
9382
9383         if (!NT_STATUS_IS_OK(state->status)) {
9384                 printf("cli_posix_getacl_recv returned %s\n",
9385                         nt_errstr(state->status));
9386         }
9387         *state->acl_ret = true;
9388 }
9389
9390 static bool run_posix_acl_oplock_test(int dummy)
9391 {
9392         struct tevent_context *ev;
9393         struct cli_state *cli1, *cli2;
9394         struct tevent_req *oplock_req, *getacl_req;
9395         const char *fname = "posix_acl_oplock";
9396         uint16_t fnum;
9397         int saved_use_oplocks = use_oplocks;
9398         NTSTATUS status;
9399         bool correct = true;
9400         bool got_break = false;
9401         bool acl_ret = false;
9402
9403         struct posix_acl_oplock_state *state;
9404
9405         printf("starting posix_acl_oplock test\n");
9406
9407         if (!torture_open_connection(&cli1, 0)) {
9408                 use_level_II_oplocks = false;
9409                 use_oplocks = saved_use_oplocks;
9410                 return false;
9411         }
9412
9413         if (!torture_open_connection(&cli2, 1)) {
9414                 use_level_II_oplocks = false;
9415                 use_oplocks = saved_use_oplocks;
9416                 return false;
9417         }
9418
9419         /* Setup posix on cli2 only. */
9420         status = torture_setup_unix_extensions(cli2);
9421         if (!NT_STATUS_IS_OK(status)) {
9422                 return false;
9423         }
9424
9425         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9426         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9427
9428         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9429
9430         /* Create the file on the Windows connection. */
9431         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9432                           &fnum);
9433         if (!NT_STATUS_IS_OK(status)) {
9434                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9435                 return false;
9436         }
9437
9438         status = cli_close(cli1, fnum);
9439         if (!NT_STATUS_IS_OK(status)) {
9440                 printf("close1 failed (%s)\n", nt_errstr(status));
9441                 return false;
9442         }
9443
9444         cli1->use_oplocks = true;
9445
9446         /* Open with oplock. */
9447         status = cli_ntcreate(cli1,
9448                         fname,
9449                         0,
9450                         FILE_READ_DATA,
9451                         FILE_ATTRIBUTE_NORMAL,
9452                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9453                         FILE_OPEN,
9454                         0,
9455                         0,
9456                         &fnum,
9457                         NULL);
9458
9459         if (!NT_STATUS_IS_OK(status)) {
9460                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9461                 return false;
9462         }
9463
9464         ev = samba_tevent_context_init(talloc_tos());
9465         if (ev == NULL) {
9466                 printf("tevent_context_init failed\n");
9467                 return false;
9468         }
9469
9470         state = talloc_zero(ev, struct posix_acl_oplock_state);
9471         if (state == NULL) {
9472                 printf("talloc failed\n");
9473                 return false;
9474         }
9475         state->ev = ev;
9476         state->cli = cli1;
9477         state->got_break = &got_break;
9478         state->acl_ret = &acl_ret;
9479
9480         oplock_req = cli_smb_oplock_break_waiter_send(
9481                 talloc_tos(), ev, cli1);
9482         if (oplock_req == NULL) {
9483                 printf("cli_smb_oplock_break_waiter_send failed\n");
9484                 return false;
9485         }
9486         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9487
9488         /* Get ACL on POSIX connection - should break oplock. */
9489         getacl_req = cli_posix_getacl_send(talloc_tos(),
9490                                 ev,
9491                                 cli2,
9492                                 fname);
9493         if (getacl_req == NULL) {
9494                 printf("cli_posix_getacl_send failed\n");
9495                 return false;
9496         }
9497         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9498
9499         while (!got_break || !acl_ret) {
9500                 int ret;
9501                 ret = tevent_loop_once(ev);
9502                 if (ret == -1) {
9503                         printf("tevent_loop_once failed: %s\n",
9504                                strerror(errno));
9505                         return false;
9506                 }
9507         }
9508
9509         if (!NT_STATUS_IS_OK(state->status)) {
9510                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9511                 correct = false;
9512         }
9513
9514         status = cli_close(cli1, fnum);
9515         if (!NT_STATUS_IS_OK(status)) {
9516                 printf("close2 failed (%s)\n", nt_errstr(status));
9517                 correct = false;
9518         }
9519
9520         status = cli_unlink(cli1,
9521                         fname,
9522                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9523         if (!NT_STATUS_IS_OK(status)) {
9524                 printf("unlink failed (%s)\n", nt_errstr(status));
9525                 correct = false;
9526         }
9527
9528         if (!torture_close_connection(cli1)) {
9529                 correct = false;
9530         }
9531         if (!torture_close_connection(cli2)) {
9532                 correct = false;
9533         }
9534
9535         if (!got_break) {
9536                 correct = false;
9537         }
9538
9539         printf("finished posix acl oplock test\n");
9540
9541         return correct;
9542 }
9543
9544 static bool run_posix_acl_shareroot_test(int dummy)
9545 {
9546         struct cli_state *cli;
9547         NTSTATUS status;
9548         bool correct = false;
9549         char *posix_acl = NULL;
9550         size_t posix_acl_len = 0;
9551         uint16_t num_file_acls = 0;
9552         uint16_t num_dir_acls = 0;
9553         uint16_t i;
9554         uint32_t expected_size = 0;
9555         bool got_user = false;
9556         bool got_group = false;
9557         bool got_other = false;
9558         TALLOC_CTX *frame = NULL;
9559
9560         frame = talloc_stackframe();
9561
9562         printf("starting posix_acl_shareroot test\n");
9563
9564         if (!torture_open_connection(&cli, 0)) {
9565                 TALLOC_FREE(frame);
9566                 return false;
9567         }
9568
9569         smbXcli_conn_set_sockopt(cli->conn, sockops);
9570
9571         status = torture_setup_unix_extensions(cli);
9572         if (!NT_STATUS_IS_OK(status)) {
9573                 printf("Failed to setup unix extensions\n");
9574                 goto out;
9575         }
9576
9577         /* Get the POSIX ACL on the root of the share. */
9578         status = cli_posix_getacl(cli,
9579                                 ".",
9580                                 frame,
9581                                 &posix_acl_len,
9582                                 &posix_acl);
9583
9584         if (!NT_STATUS_IS_OK(status)) {
9585                 printf("cli_posix_getacl of '.' failed (%s)\n",
9586                         nt_errstr(status));
9587                 goto out;
9588         }
9589
9590         if (posix_acl_len < 6 ||
9591                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9592                 printf("getfacl ., unknown POSIX acl version %u.\n",
9593                         (unsigned int)CVAL(posix_acl,0) );
9594                 goto out;
9595         }
9596
9597         num_file_acls = SVAL(posix_acl,2);
9598         num_dir_acls = SVAL(posix_acl,4);
9599         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9600                                 SMB_POSIX_ACL_ENTRY_SIZE*
9601                                 (num_file_acls+num_dir_acls);
9602
9603         if (posix_acl_len != expected_size) {
9604                 printf("incorrect POSIX acl buffer size "
9605                         "(should be %u, was %u).\n",
9606                         (unsigned int)expected_size,
9607                         (unsigned int)posix_acl_len);
9608                 goto out;
9609         }
9610
9611         /*
9612          * We don't need to know what the ACL's are
9613          * we just need to know we have at least 3
9614          * file entries (u,g,o).
9615          */
9616
9617         for (i = 0; i < num_file_acls; i++) {
9618                 unsigned char tagtype =
9619                         CVAL(posix_acl,
9620                                 SMB_POSIX_ACL_HEADER_SIZE+
9621                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9622
9623                 switch(tagtype) {
9624                         case SMB_POSIX_ACL_USER_OBJ:
9625                                 got_user = true;
9626                                 break;
9627                         case SMB_POSIX_ACL_GROUP_OBJ:
9628                                 got_group = true;
9629                                 break;
9630                         case SMB_POSIX_ACL_OTHER:
9631                                 got_other = true;
9632                                 break;
9633                         default:
9634                                 break;
9635                 }
9636         }
9637
9638         if (!got_user) {
9639                 printf("Missing user entry\n");
9640                 goto out;
9641         }
9642
9643         if (!got_group) {
9644                 printf("Missing group entry\n");
9645                 goto out;
9646         }
9647
9648         if (!got_other) {
9649                 printf("Missing other entry\n");
9650                 goto out;
9651         }
9652
9653         correct = true;
9654
9655   out:
9656
9657         if (!torture_close_connection(cli)) {
9658                 correct = false;
9659         }
9660
9661         printf("finished posix acl shareroot test\n");
9662         TALLOC_FREE(frame);
9663
9664         return correct;
9665 }
9666
9667 static uint32_t open_attrs_table[] = {
9668                 FILE_ATTRIBUTE_NORMAL,
9669                 FILE_ATTRIBUTE_ARCHIVE,
9670                 FILE_ATTRIBUTE_READONLY,
9671                 FILE_ATTRIBUTE_HIDDEN,
9672                 FILE_ATTRIBUTE_SYSTEM,
9673
9674                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9675                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9676                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9677                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9678                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9679                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9680
9681                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9682                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9683                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9684                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9685 };
9686
9687 struct trunc_open_results {
9688         unsigned int num;
9689         uint32_t init_attr;
9690         uint32_t trunc_attr;
9691         uint32_t result_attr;
9692 };
9693
9694 static struct trunc_open_results attr_results[] = {
9695         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9696         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9697         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9698         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9699         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9700         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9701         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9702         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9703         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9704         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9705         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9706         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9707         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9708         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9709         { 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 },
9710         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9711         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9712         { 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 },
9713         { 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 },
9714         { 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 },
9715         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9717         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9718         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9720         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9721 };
9722
9723 static bool run_openattrtest(int dummy)
9724 {
9725         static struct cli_state *cli1;
9726         const char *fname = "\\openattr.file";
9727         uint16_t fnum1;
9728         bool correct = True;
9729         uint32_t attr;
9730         unsigned int i, j, k, l;
9731         NTSTATUS status;
9732
9733         printf("starting open attr test\n");
9734
9735         if (!torture_open_connection(&cli1, 0)) {
9736                 return False;
9737         }
9738
9739         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9740
9741         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9742                 cli_setatr(cli1, fname, 0, 0);
9743                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9744
9745                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9746                                        open_attrs_table[i], FILE_SHARE_NONE,
9747                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9748                 if (!NT_STATUS_IS_OK(status)) {
9749                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9750                         return False;
9751                 }
9752
9753                 status = cli_close(cli1, fnum1);
9754                 if (!NT_STATUS_IS_OK(status)) {
9755                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9756                         return False;
9757                 }
9758
9759                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9760                         status = cli_ntcreate(cli1, fname, 0,
9761                                               FILE_READ_DATA|FILE_WRITE_DATA,
9762                                               open_attrs_table[j],
9763                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9764                                               0, 0, &fnum1, NULL);
9765                         if (!NT_STATUS_IS_OK(status)) {
9766                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9767                                         if (attr_results[l].num == k) {
9768                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9769                                                                 k, open_attrs_table[i],
9770                                                                 open_attrs_table[j],
9771                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9772                                                 correct = False;
9773                                         }
9774                                 }
9775
9776                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9777                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9778                                                         k, open_attrs_table[i], open_attrs_table[j],
9779                                                         nt_errstr(status));
9780                                         correct = False;
9781                                 }
9782 #if 0
9783                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9784 #endif
9785                                 k++;
9786                                 continue;
9787                         }
9788
9789                         status = cli_close(cli1, fnum1);
9790                         if (!NT_STATUS_IS_OK(status)) {
9791                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9792                                 return False;
9793                         }
9794
9795                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9796                         if (!NT_STATUS_IS_OK(status)) {
9797                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9798                                 return False;
9799                         }
9800
9801 #if 0
9802                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9803                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9804 #endif
9805
9806                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9807                                 if (attr_results[l].num == k) {
9808                                         if (attr != attr_results[l].result_attr ||
9809                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9810                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9811                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9812                                                 open_attrs_table[i],
9813                                                 open_attrs_table[j],
9814                                                 (unsigned int)attr,
9815                                                 attr_results[l].result_attr);
9816                                                 correct = False;
9817                                         }
9818                                         break;
9819                                 }
9820                         }
9821                         k++;
9822                 }
9823         }
9824
9825         cli_setatr(cli1, fname, 0, 0);
9826         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9827
9828         printf("open attr test %s.\n", correct ? "passed" : "failed");
9829
9830         if (!torture_close_connection(cli1)) {
9831                 correct = False;
9832         }
9833         return correct;
9834 }
9835
9836 static NTSTATUS list_fn(struct file_info *finfo,
9837                     const char *name, void *state)
9838 {
9839         int *matched = (int *)state;
9840         if (matched != NULL) {
9841                 *matched += 1;
9842         }
9843         return NT_STATUS_OK;
9844 }
9845
9846 /*
9847   test directory listing speed
9848  */
9849 static bool run_dirtest(int dummy)
9850 {
9851         int i;
9852         static struct cli_state *cli;
9853         uint16_t fnum;
9854         struct timeval core_start;
9855         bool correct = True;
9856         int matched;
9857
9858         printf("starting directory test\n");
9859
9860         if (!torture_open_connection(&cli, 0)) {
9861                 return False;
9862         }
9863
9864         smbXcli_conn_set_sockopt(cli->conn, sockops);
9865
9866         srandom(0);
9867         for (i=0;i<torture_numops;i++) {
9868                 fstring fname;
9869                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9870                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9871                         fprintf(stderr,"Failed to open %s\n", fname);
9872                         return False;
9873                 }
9874                 cli_close(cli, fnum);
9875         }
9876
9877         core_start = timeval_current();
9878
9879         matched = 0;
9880         cli_list(cli, "a*.*", 0, list_fn, &matched);
9881         printf("Matched %d\n", matched);
9882
9883         matched = 0;
9884         cli_list(cli, "b*.*", 0, list_fn, &matched);
9885         printf("Matched %d\n", matched);
9886
9887         matched = 0;
9888         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9889         printf("Matched %d\n", matched);
9890
9891         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9892
9893         srandom(0);
9894         for (i=0;i<torture_numops;i++) {
9895                 fstring fname;
9896                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9897                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9898         }
9899
9900         if (!torture_close_connection(cli)) {
9901                 correct = False;
9902         }
9903
9904         printf("finished dirtest\n");
9905
9906         return correct;
9907 }
9908
9909 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9910                    void *state)
9911 {
9912         struct cli_state *pcli = (struct cli_state *)state;
9913         fstring fname;
9914         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9915
9916         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9917                 return NT_STATUS_OK;
9918
9919         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9920                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9921                         printf("del_fn: failed to rmdir %s\n,", fname );
9922         } else {
9923                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9924                         printf("del_fn: failed to unlink %s\n,", fname );
9925         }
9926         return NT_STATUS_OK;
9927 }
9928
9929
9930 /*
9931    send a raw ioctl - used by the torture code
9932 */
9933 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9934                               uint16_t fnum,
9935                               uint32_t code,
9936                               DATA_BLOB *blob)
9937 {
9938         uint16_t vwv[3];
9939         NTSTATUS status;
9940
9941         PUSH_LE_U16(vwv + 0, 0, fnum);
9942         PUSH_LE_U16(vwv + 1, 0, code >> 16);
9943         PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9944
9945         status = cli_smb(talloc_tos(),
9946                          cli,
9947                          SMBioctl,
9948                          0,
9949                          3,
9950                          vwv,
9951                          0,
9952                          NULL,
9953                          NULL,
9954                          0,
9955                          NULL,
9956                          NULL,
9957                          NULL,
9958                          NULL);
9959         if (!NT_STATUS_IS_OK(status)) {
9960                 return status;
9961         }
9962         *blob = data_blob_null;
9963         return NT_STATUS_OK;
9964 }
9965
9966 /*
9967   sees what IOCTLs are supported
9968  */
9969 bool torture_ioctl_test(int dummy)
9970 {
9971         static struct cli_state *cli;
9972         uint16_t device, function;
9973         uint16_t fnum;
9974         const char *fname = "\\ioctl.dat";
9975         DATA_BLOB blob;
9976         NTSTATUS status;
9977
9978         if (!torture_open_connection(&cli, 0)) {
9979                 return False;
9980         }
9981
9982         printf("starting ioctl test\n");
9983
9984         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9985
9986         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9987         if (!NT_STATUS_IS_OK(status)) {
9988                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9989                 return False;
9990         }
9991
9992         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9993         printf("ioctl device info: %s\n", nt_errstr(status));
9994
9995         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9996         printf("ioctl job info: %s\n", nt_errstr(status));
9997
9998         for (device=0;device<0x100;device++) {
9999                 printf("ioctl test with device = 0x%x\n", device);
10000                 for (function=0;function<0x100;function++) {
10001                         uint32_t code = (device<<16) | function;
10002
10003                         status = cli_raw_ioctl(cli, fnum, code, &blob);
10004
10005                         if (NT_STATUS_IS_OK(status)) {
10006                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10007                                        (int)blob.length);
10008                                 data_blob_free(&blob);
10009                         }
10010                 }
10011         }
10012
10013         if (!torture_close_connection(cli)) {
10014                 return False;
10015         }
10016
10017         return True;
10018 }
10019
10020
10021 /*
10022   tries variants of chkpath
10023  */
10024 bool torture_chkpath_test(int dummy)
10025 {
10026         static struct cli_state *cli;
10027         uint16_t fnum;
10028         bool ret;
10029         NTSTATUS status;
10030
10031         if (!torture_open_connection(&cli, 0)) {
10032                 return False;
10033         }
10034
10035         printf("starting chkpath test\n");
10036
10037         /* cleanup from an old run */
10038         torture_deltree(cli, "\\chkpath.dir");
10039
10040         status = cli_mkdir(cli, "\\chkpath.dir");
10041         if (!NT_STATUS_IS_OK(status)) {
10042                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10043                 return False;
10044         }
10045
10046         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10047         if (!NT_STATUS_IS_OK(status)) {
10048                 printf("mkdir2 failed : %s\n", nt_errstr(status));
10049                 return False;
10050         }
10051
10052         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10053                           DENY_NONE, &fnum);
10054         if (!NT_STATUS_IS_OK(status)) {
10055                 printf("open1 failed (%s)\n", nt_errstr(status));
10056                 return False;
10057         }
10058         cli_close(cli, fnum);
10059
10060         status = cli_chkpath(cli, "\\chkpath.dir");
10061         if (!NT_STATUS_IS_OK(status)) {
10062                 printf("chkpath1 failed: %s\n", nt_errstr(status));
10063                 ret = False;
10064         }
10065
10066         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10067         if (!NT_STATUS_IS_OK(status)) {
10068                 printf("chkpath2 failed: %s\n", nt_errstr(status));
10069                 ret = False;
10070         }
10071
10072         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10073         if (!NT_STATUS_IS_OK(status)) {
10074                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10075                                   NT_STATUS_NOT_A_DIRECTORY);
10076         } else {
10077                 printf("* chkpath on a file should fail\n");
10078                 ret = False;
10079         }
10080
10081         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10082         if (!NT_STATUS_IS_OK(status)) {
10083                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10084                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
10085         } else {
10086                 printf("* chkpath on a non existent file should fail\n");
10087                 ret = False;
10088         }
10089
10090         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10091         if (!NT_STATUS_IS_OK(status)) {
10092                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10093                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
10094         } else {
10095                 printf("* chkpath on a non existent component should fail\n");
10096                 ret = False;
10097         }
10098
10099         torture_deltree(cli, "\\chkpath.dir");
10100
10101         if (!torture_close_connection(cli)) {
10102                 return False;
10103         }
10104
10105         return ret;
10106 }
10107
10108 static bool run_eatest(int dummy)
10109 {
10110         static struct cli_state *cli;
10111         const char *fname = "\\eatest.txt";
10112         bool correct = True;
10113         uint16_t fnum;
10114         size_t i, num_eas;
10115         struct ea_struct *ea_list = NULL;
10116         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10117         NTSTATUS status;
10118
10119         printf("starting eatest\n");
10120
10121         if (!torture_open_connection(&cli, 0)) {
10122                 talloc_destroy(mem_ctx);
10123                 return False;
10124         }
10125
10126         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10127
10128         status = cli_ntcreate(cli, fname, 0,
10129                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10130                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10131                               0x4044, 0, &fnum, NULL);
10132         if (!NT_STATUS_IS_OK(status)) {
10133                 printf("open failed - %s\n", nt_errstr(status));
10134                 talloc_destroy(mem_ctx);
10135                 return False;
10136         }
10137
10138         for (i = 0; i < 10; i++) {
10139                 fstring ea_name, ea_val;
10140
10141                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10142                 memset(ea_val, (char)i+1, i+1);
10143                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10144                 if (!NT_STATUS_IS_OK(status)) {
10145                         printf("ea_set of name %s failed - %s\n", ea_name,
10146                                nt_errstr(status));
10147                         talloc_destroy(mem_ctx);
10148                         return False;
10149                 }
10150         }
10151
10152         cli_close(cli, fnum);
10153         for (i = 0; i < 10; i++) {
10154                 fstring ea_name, ea_val;
10155
10156                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10157                 memset(ea_val, (char)i+1, i+1);
10158                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10159                 if (!NT_STATUS_IS_OK(status)) {
10160                         printf("ea_set of name %s failed - %s\n", ea_name,
10161                                nt_errstr(status));
10162                         talloc_destroy(mem_ctx);
10163                         return False;
10164                 }
10165         }
10166
10167         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10168         if (!NT_STATUS_IS_OK(status)) {
10169                 printf("ea_get list failed - %s\n", nt_errstr(status));
10170                 correct = False;
10171         }
10172
10173         printf("num_eas = %d\n", (int)num_eas);
10174
10175         if (num_eas != 20) {
10176                 printf("Should be 20 EA's stored... failing.\n");
10177                 correct = False;
10178         }
10179
10180         for (i = 0; i < num_eas; i++) {
10181                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10182                 dump_data(0, ea_list[i].value.data,
10183                           ea_list[i].value.length);
10184         }
10185
10186         /* Setting EA's to zero length deletes them. Test this */
10187         printf("Now deleting all EA's - case independent....\n");
10188
10189 #if 1
10190         cli_set_ea_path(cli, fname, "", "", 0);
10191 #else
10192         for (i = 0; i < 20; i++) {
10193                 fstring ea_name;
10194                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10195                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10196                 if (!NT_STATUS_IS_OK(status)) {
10197                         printf("ea_set of name %s failed - %s\n", ea_name,
10198                                nt_errstr(status));
10199                         talloc_destroy(mem_ctx);
10200                         return False;
10201                 }
10202         }
10203 #endif
10204
10205         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10206         if (!NT_STATUS_IS_OK(status)) {
10207                 printf("ea_get list failed - %s\n", nt_errstr(status));
10208                 correct = False;
10209         }
10210
10211         printf("num_eas = %d\n", (int)num_eas);
10212         for (i = 0; i < num_eas; i++) {
10213                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10214                 dump_data(0, ea_list[i].value.data,
10215                           ea_list[i].value.length);
10216         }
10217
10218         if (num_eas != 0) {
10219                 printf("deleting EA's failed.\n");
10220                 correct = False;
10221         }
10222
10223         /* Try and delete a non existent EA. */
10224         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10225         if (!NT_STATUS_IS_OK(status)) {
10226                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10227                        nt_errstr(status));
10228                 correct = False;
10229         }
10230
10231         talloc_destroy(mem_ctx);
10232         if (!torture_close_connection(cli)) {
10233                 correct = False;
10234         }
10235
10236         return correct;
10237 }
10238
10239 static bool run_dirtest1(int dummy)
10240 {
10241         int i;
10242         static struct cli_state *cli;
10243         uint16_t fnum;
10244         int num_seen;
10245         bool correct = True;
10246
10247         printf("starting directory test\n");
10248
10249         if (!torture_open_connection(&cli, 0)) {
10250                 return False;
10251         }
10252
10253         smbXcli_conn_set_sockopt(cli->conn, sockops);
10254
10255         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10256         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10257         cli_rmdir(cli, "\\LISTDIR");
10258         cli_mkdir(cli, "\\LISTDIR");
10259
10260         /* Create 1000 files and 1000 directories. */
10261         for (i=0;i<1000;i++) {
10262                 fstring fname;
10263                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10264                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10265                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10266                                    0, 0, &fnum, NULL))) {
10267                         fprintf(stderr,"Failed to open %s\n", fname);
10268                         return False;
10269                 }
10270                 cli_close(cli, fnum);
10271         }
10272         for (i=0;i<1000;i++) {
10273                 fstring fname;
10274                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10275                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10276                         fprintf(stderr,"Failed to open %s\n", fname);
10277                         return False;
10278                 }
10279         }
10280
10281         /* Now ensure that doing an old list sees both files and directories. */
10282         num_seen = 0;
10283         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10284         printf("num_seen = %d\n", num_seen );
10285         /* We should see 100 files + 1000 directories + . and .. */
10286         if (num_seen != 2002)
10287                 correct = False;
10288
10289         /* Ensure if we have the "must have" bits we only see the
10290          * relevant entries.
10291          */
10292         num_seen = 0;
10293         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10294         printf("num_seen = %d\n", num_seen );
10295         if (num_seen != 1002)
10296                 correct = False;
10297
10298         num_seen = 0;
10299         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10300         printf("num_seen = %d\n", num_seen );
10301         if (num_seen != 1000)
10302                 correct = False;
10303
10304         /* Delete everything. */
10305         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10306         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10307         cli_rmdir(cli, "\\LISTDIR");
10308
10309 #if 0
10310         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10311         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10312         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10313 #endif
10314
10315         if (!torture_close_connection(cli)) {
10316                 correct = False;
10317         }
10318
10319         printf("finished dirtest1\n");
10320
10321         return correct;
10322 }
10323
10324 static bool run_error_map_extract(int dummy) {
10325
10326         static struct cli_state *c_dos;
10327         static struct cli_state *c_nt;
10328         NTSTATUS status;
10329
10330         uint32_t error;
10331
10332         uint32_t errnum;
10333         uint8_t errclass;
10334
10335         NTSTATUS nt_status;
10336
10337         fstring user;
10338
10339         /* NT-Error connection */
10340
10341         disable_spnego = true;
10342         if (!(c_nt = open_nbt_connection())) {
10343                 disable_spnego = false;
10344                 return False;
10345         }
10346         disable_spnego = false;
10347
10348         status = smbXcli_negprot(c_nt->conn,
10349                                  c_nt->timeout,
10350                                  PROTOCOL_CORE,
10351                                  PROTOCOL_NT1,
10352                                  NULL,
10353                                  NULL,
10354                                  NULL);
10355
10356         if (!NT_STATUS_IS_OK(status)) {
10357                 printf("%s rejected the NT-error negprot (%s)\n", host,
10358                        nt_errstr(status));
10359                 cli_shutdown(c_nt);
10360                 return False;
10361         }
10362
10363         status = cli_session_setup_anon(c_nt);
10364         if (!NT_STATUS_IS_OK(status)) {
10365                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10366                 return False;
10367         }
10368
10369         /* DOS-Error connection */
10370
10371         disable_spnego = true;
10372         force_dos_errors = true;
10373         if (!(c_dos = open_nbt_connection())) {
10374                 disable_spnego = false;
10375                 force_dos_errors = false;
10376                 return False;
10377         }
10378         disable_spnego = false;
10379         force_dos_errors = false;
10380
10381         status = smbXcli_negprot(c_dos->conn,
10382                                  c_dos->timeout,
10383                                  PROTOCOL_CORE,
10384                                  PROTOCOL_NT1,
10385                                  NULL,
10386                                  NULL,
10387                                  NULL);
10388         if (!NT_STATUS_IS_OK(status)) {
10389                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10390                        nt_errstr(status));
10391                 cli_shutdown(c_dos);
10392                 return False;
10393         }
10394
10395         status = cli_session_setup_anon(c_dos);
10396         if (!NT_STATUS_IS_OK(status)) {
10397                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10398                         host, nt_errstr(status));
10399                 return False;
10400         }
10401
10402         c_nt->map_dos_errors = false;
10403         c_dos->map_dos_errors = false;
10404
10405         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10406                 struct cli_credentials *user_creds = NULL;
10407
10408                 fstr_sprintf(user, "%X", error);
10409
10410                 user_creds = cli_session_creds_init(talloc_tos(),
10411                                                     user,
10412                                                     workgroup,
10413                                                     NULL, /* realm */
10414                                                     password,
10415                                                     false, /* use_kerberos */
10416                                                     false, /* fallback_after_kerberos */
10417                                                     false, /* use_ccache */
10418                                                     false); /* password_is_nt_hash */
10419                 if (user_creds == NULL) {
10420                         printf("cli_session_creds_init(%s) failed\n", user);
10421                         return false;
10422                 }
10423
10424                 status = cli_session_setup_creds(c_nt, user_creds);
10425                 if (NT_STATUS_IS_OK(status)) {
10426                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10427                 }
10428
10429                 /* Case #1: 32-bit NT errors */
10430                 if (!NT_STATUS_IS_DOS(status)) {
10431                         nt_status = status;
10432                 } else {
10433                         printf("/** Dos error on NT connection! (%s) */\n",
10434                                nt_errstr(status));
10435                         nt_status = NT_STATUS(0xc0000000);
10436                 }
10437
10438                 status = cli_session_setup_creds(c_dos, user_creds);
10439                 if (NT_STATUS_IS_OK(status)) {
10440                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10441                 }
10442
10443                 /* Case #1: 32-bit NT errors */
10444                 if (NT_STATUS_IS_DOS(status)) {
10445                         printf("/** NT error on DOS connection! (%s) */\n",
10446                                nt_errstr(status));
10447                         errnum = errclass = 0;
10448                 } else {
10449                         errclass = NT_STATUS_DOS_CLASS(status);
10450                         errnum = NT_STATUS_DOS_CODE(status);
10451                 }
10452
10453                 if (NT_STATUS_V(nt_status) != error) {
10454                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10455                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10456                                get_nt_error_c_code(talloc_tos(), nt_status));
10457                 }
10458
10459                 printf("\t{%s,\t%s,\t%s},\n",
10460                        smb_dos_err_class(errclass),
10461                        smb_dos_err_name(errclass, errnum),
10462                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10463
10464                 TALLOC_FREE(user_creds);
10465         }
10466         return True;
10467 }
10468
10469 static bool run_sesssetup_bench(int dummy)
10470 {
10471         static struct cli_state *c;
10472         const char *fname = "\\file.dat";
10473         uint16_t fnum;
10474         NTSTATUS status;
10475         int i;
10476
10477         if (!torture_open_connection(&c, 0)) {
10478                 return false;
10479         }
10480
10481         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10482                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10483                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10484         if (!NT_STATUS_IS_OK(status)) {
10485                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10486                 return false;
10487         }
10488
10489         for (i=0; i<torture_numops; i++) {
10490                 status = cli_session_setup_creds(c, torture_creds);
10491                 if (!NT_STATUS_IS_OK(status)) {
10492                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10493                                  __location__, nt_errstr(status));
10494                         return false;
10495                 }
10496
10497                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10498
10499                 status = cli_ulogoff(c);
10500                 if (!NT_STATUS_IS_OK(status)) {
10501                         d_printf("(%s) cli_ulogoff failed: %s\n",
10502                                  __location__, nt_errstr(status));
10503                         return false;
10504                 }
10505         }
10506
10507         return true;
10508 }
10509
10510 static bool subst_test(const char *str, const char *user, const char *domain,
10511                        uid_t uid, gid_t gid, const char *expected)
10512 {
10513         char *subst;
10514         bool result = true;
10515
10516         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10517
10518         if (strcmp(subst, expected) != 0) {
10519                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10520                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10521                        expected);
10522                 result = false;
10523         }
10524
10525         TALLOC_FREE(subst);
10526         return result;
10527 }
10528
10529 static void chain1_open_completion(struct tevent_req *req)
10530 {
10531         uint16_t fnum;
10532         NTSTATUS status;
10533         status = cli_openx_recv(req, &fnum);
10534         TALLOC_FREE(req);
10535
10536         d_printf("cli_openx_recv returned %s: %d\n",
10537                  nt_errstr(status),
10538                  NT_STATUS_IS_OK(status) ? fnum : -1);
10539 }
10540
10541 static void chain1_write_completion(struct tevent_req *req)
10542 {
10543         size_t written;
10544         NTSTATUS status;
10545         status = cli_write_andx_recv(req, &written);
10546         TALLOC_FREE(req);
10547
10548         d_printf("cli_write_andx_recv returned %s: %d\n",
10549                  nt_errstr(status),
10550                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10551 }
10552
10553 static void chain1_close_completion(struct tevent_req *req)
10554 {
10555         NTSTATUS status;
10556         bool *done = (bool *)tevent_req_callback_data_void(req);
10557
10558         status = cli_close_recv(req);
10559         *done = true;
10560
10561         TALLOC_FREE(req);
10562
10563         d_printf("cli_close returned %s\n", nt_errstr(status));
10564 }
10565
10566 static bool run_chain1(int dummy)
10567 {
10568         struct cli_state *cli1;
10569         struct tevent_context *evt = samba_tevent_context_init(NULL);
10570         struct tevent_req *reqs[3], *smbreqs[3];
10571         bool done = false;
10572         const char *str = "foobar";
10573         const char *fname = "\\test_chain";
10574         NTSTATUS status;
10575
10576         printf("starting chain1 test\n");
10577         if (!torture_open_connection(&cli1, 0)) {
10578                 return False;
10579         }
10580
10581         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10582
10583         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10584
10585         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10586                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10587         if (reqs[0] == NULL) return false;
10588         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10589
10590
10591         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10592                                         (const uint8_t *)str, 0, strlen(str)+1,
10593                                         smbreqs, 1, &smbreqs[1]);
10594         if (reqs[1] == NULL) return false;
10595         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10596
10597         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10598         if (reqs[2] == NULL) return false;
10599         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10600
10601         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10602         if (!NT_STATUS_IS_OK(status)) {
10603                 return false;
10604         }
10605
10606         while (!done) {
10607                 tevent_loop_once(evt);
10608         }
10609
10610         torture_close_connection(cli1);
10611         return True;
10612 }
10613
10614 static void chain2_sesssetup_completion(struct tevent_req *req)
10615 {
10616         NTSTATUS status;
10617         status = cli_session_setup_guest_recv(req);
10618         d_printf("sesssetup returned %s\n", nt_errstr(status));
10619 }
10620
10621 static void chain2_tcon_completion(struct tevent_req *req)
10622 {
10623         bool *done = (bool *)tevent_req_callback_data_void(req);
10624         NTSTATUS status;
10625         status = cli_tcon_andx_recv(req);
10626         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10627         *done = true;
10628 }
10629
10630 static bool run_chain2(int dummy)
10631 {
10632         struct cli_state *cli1;
10633         struct tevent_context *evt = samba_tevent_context_init(NULL);
10634         struct tevent_req *reqs[2], *smbreqs[2];
10635         bool done = false;
10636         NTSTATUS status;
10637         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10638
10639         printf("starting chain2 test\n");
10640         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10641                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10642         if (!NT_STATUS_IS_OK(status)) {
10643                 return False;
10644         }
10645
10646         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10647
10648         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10649                                                  &smbreqs[0]);
10650         if (reqs[0] == NULL) return false;
10651         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10652
10653         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10654                                        "?????", NULL, 0, &smbreqs[1]);
10655         if (reqs[1] == NULL) return false;
10656         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10657
10658         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10659         if (!NT_STATUS_IS_OK(status)) {
10660                 return false;
10661         }
10662
10663         while (!done) {
10664                 tevent_loop_once(evt);
10665         }
10666
10667         torture_close_connection(cli1);
10668         return True;
10669 }
10670
10671
10672 struct torture_createdel_state {
10673         struct tevent_context *ev;
10674         struct cli_state *cli;
10675 };
10676
10677 static void torture_createdel_created(struct tevent_req *subreq);
10678 static void torture_createdel_closed(struct tevent_req *subreq);
10679
10680 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10681                                                  struct tevent_context *ev,
10682                                                  struct cli_state *cli,
10683                                                  const char *name)
10684 {
10685         struct tevent_req *req, *subreq;
10686         struct torture_createdel_state *state;
10687
10688         req = tevent_req_create(mem_ctx, &state,
10689                                 struct torture_createdel_state);
10690         if (req == NULL) {
10691                 return NULL;
10692         }
10693         state->ev = ev;
10694         state->cli = cli;
10695
10696         subreq = cli_ntcreate_send(
10697                 state, ev, cli, name, 0,
10698                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10699                 FILE_ATTRIBUTE_NORMAL,
10700                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10701                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10702                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10703
10704         if (tevent_req_nomem(subreq, req)) {
10705                 return tevent_req_post(req, ev);
10706         }
10707         tevent_req_set_callback(subreq, torture_createdel_created, req);
10708         return req;
10709 }
10710
10711 static void torture_createdel_created(struct tevent_req *subreq)
10712 {
10713         struct tevent_req *req = tevent_req_callback_data(
10714                 subreq, struct tevent_req);
10715         struct torture_createdel_state *state = tevent_req_data(
10716                 req, struct torture_createdel_state);
10717         NTSTATUS status;
10718         uint16_t fnum;
10719
10720         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10721         TALLOC_FREE(subreq);
10722         if (tevent_req_nterror(req, status)) {
10723                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10724                            nt_errstr(status)));
10725                 return;
10726         }
10727
10728         subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10729         if (tevent_req_nomem(subreq, req)) {
10730                 return;
10731         }
10732         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10733 }
10734
10735 static void torture_createdel_closed(struct tevent_req *subreq)
10736 {
10737         struct tevent_req *req = tevent_req_callback_data(
10738                 subreq, struct tevent_req);
10739         NTSTATUS status;
10740
10741         status = cli_close_recv(subreq);
10742         if (tevent_req_nterror(req, status)) {
10743                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10744                 return;
10745         }
10746         tevent_req_done(req);
10747 }
10748
10749 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10750 {
10751         return tevent_req_simple_recv_ntstatus(req);
10752 }
10753
10754 struct torture_createdels_state {
10755         struct tevent_context *ev;
10756         struct cli_state *cli;
10757         const char *base_name;
10758         int sent;
10759         int received;
10760         int num_files;
10761         struct tevent_req **reqs;
10762 };
10763
10764 static void torture_createdels_done(struct tevent_req *subreq);
10765
10766 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10767                                                   struct tevent_context *ev,
10768                                                   struct cli_state *cli,
10769                                                   const char *base_name,
10770                                                   int num_parallel,
10771                                                   int num_files)
10772 {
10773         struct tevent_req *req;
10774         struct torture_createdels_state *state;
10775         int i;
10776
10777         req = tevent_req_create(mem_ctx, &state,
10778                                 struct torture_createdels_state);
10779         if (req == NULL) {
10780                 return NULL;
10781         }
10782         state->ev = ev;
10783         state->cli = cli;
10784         state->base_name = talloc_strdup(state, base_name);
10785         if (tevent_req_nomem(state->base_name, req)) {
10786                 return tevent_req_post(req, ev);
10787         }
10788         state->num_files = MAX(num_parallel, num_files);
10789         state->sent = 0;
10790         state->received = 0;
10791
10792         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10793         if (tevent_req_nomem(state->reqs, req)) {
10794                 return tevent_req_post(req, ev);
10795         }
10796
10797         for (i=0; i<num_parallel; i++) {
10798                 char *name;
10799
10800                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10801                                        state->sent);
10802                 if (tevent_req_nomem(name, req)) {
10803                         return tevent_req_post(req, ev);
10804                 }
10805                 state->reqs[i] = torture_createdel_send(
10806                         state->reqs, state->ev, state->cli, name);
10807                 if (tevent_req_nomem(state->reqs[i], req)) {
10808                         return tevent_req_post(req, ev);
10809                 }
10810                 name = talloc_move(state->reqs[i], &name);
10811                 tevent_req_set_callback(state->reqs[i],
10812                                         torture_createdels_done, req);
10813                 state->sent += 1;
10814         }
10815         return req;
10816 }
10817
10818 static void torture_createdels_done(struct tevent_req *subreq)
10819 {
10820         struct tevent_req *req = tevent_req_callback_data(
10821                 subreq, struct tevent_req);
10822         struct torture_createdels_state *state = tevent_req_data(
10823                 req, struct torture_createdels_state);
10824         size_t i, num_parallel = talloc_array_length(state->reqs);
10825         NTSTATUS status;
10826         char *name;
10827
10828         status = torture_createdel_recv(subreq);
10829         if (!NT_STATUS_IS_OK(status)){
10830                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10831                            nt_errstr(status)));
10832                 TALLOC_FREE(subreq);
10833                 tevent_req_nterror(req, status);
10834                 return;
10835         }
10836
10837         for (i=0; i<num_parallel; i++) {
10838                 if (subreq == state->reqs[i]) {
10839                         break;
10840                 }
10841         }
10842         if (i == num_parallel) {
10843                 DEBUG(10, ("received something we did not send\n"));
10844                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10845                 return;
10846         }
10847         TALLOC_FREE(state->reqs[i]);
10848
10849         if (state->sent >= state->num_files) {
10850                 tevent_req_done(req);
10851                 return;
10852         }
10853
10854         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10855                                state->sent);
10856         if (tevent_req_nomem(name, req)) {
10857                 return;
10858         }
10859         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10860                                                 state->cli, name);
10861         if (tevent_req_nomem(state->reqs[i], req)) {
10862                 return;
10863         }
10864         name = talloc_move(state->reqs[i], &name);
10865         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10866         state->sent += 1;
10867 }
10868
10869 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10870 {
10871         return tevent_req_simple_recv_ntstatus(req);
10872 }
10873
10874 struct swallow_notify_state {
10875         struct tevent_context *ev;
10876         struct cli_state *cli;
10877         uint16_t fnum;
10878         uint32_t completion_filter;
10879         bool recursive;
10880         bool (*fn)(uint32_t action, const char *name, void *priv);
10881         void *priv;
10882 };
10883
10884 static void swallow_notify_done(struct tevent_req *subreq);
10885
10886 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10887                                               struct tevent_context *ev,
10888                                               struct cli_state *cli,
10889                                               uint16_t fnum,
10890                                               uint32_t completion_filter,
10891                                               bool recursive,
10892                                               bool (*fn)(uint32_t action,
10893                                                          const char *name,
10894                                                          void *priv),
10895                                               void *priv)
10896 {
10897         struct tevent_req *req, *subreq;
10898         struct swallow_notify_state *state;
10899
10900         req = tevent_req_create(mem_ctx, &state,
10901                                 struct swallow_notify_state);
10902         if (req == NULL) {
10903                 return NULL;
10904         }
10905         state->ev = ev;
10906         state->cli = cli;
10907         state->fnum = fnum;
10908         state->completion_filter = completion_filter;
10909         state->recursive = recursive;
10910         state->fn = fn;
10911         state->priv = priv;
10912
10913         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10914                                  0xffff, state->completion_filter,
10915                                  state->recursive);
10916         if (tevent_req_nomem(subreq, req)) {
10917                 return tevent_req_post(req, ev);
10918         }
10919         tevent_req_set_callback(subreq, swallow_notify_done, req);
10920         return req;
10921 }
10922
10923 static void swallow_notify_done(struct tevent_req *subreq)
10924 {
10925         struct tevent_req *req = tevent_req_callback_data(
10926                 subreq, struct tevent_req);
10927         struct swallow_notify_state *state = tevent_req_data(
10928                 req, struct swallow_notify_state);
10929         NTSTATUS status;
10930         uint32_t i, num_changes;
10931         struct notify_change *changes;
10932
10933         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10934         TALLOC_FREE(subreq);
10935         if (!NT_STATUS_IS_OK(status)) {
10936                 DEBUG(10, ("cli_notify_recv returned %s\n",
10937                            nt_errstr(status)));
10938                 tevent_req_nterror(req, status);
10939                 return;
10940         }
10941
10942         for (i=0; i<num_changes; i++) {
10943                 state->fn(changes[i].action, changes[i].name, state->priv);
10944         }
10945         TALLOC_FREE(changes);
10946
10947         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10948                                  0xffff, state->completion_filter,
10949                                  state->recursive);
10950         if (tevent_req_nomem(subreq, req)) {
10951                 return;
10952         }
10953         tevent_req_set_callback(subreq, swallow_notify_done, req);
10954 }
10955
10956 static bool print_notifies(uint32_t action, const char *name, void *priv)
10957 {
10958         if (DEBUGLEVEL > 5) {
10959                 d_printf("%d %s\n", (int)action, name);
10960         }
10961         return true;
10962 }
10963
10964 static void notify_bench_done(struct tevent_req *req)
10965 {
10966         int *num_finished = (int *)tevent_req_callback_data_void(req);
10967         *num_finished += 1;
10968 }
10969
10970 static bool run_notify_bench(int dummy)
10971 {
10972         const char *dname = "\\notify-bench";
10973         struct tevent_context *ev;
10974         NTSTATUS status;
10975         uint16_t dnum;
10976         struct tevent_req *req1;
10977         struct tevent_req *req2 = NULL;
10978         int i, num_unc_names;
10979         int num_finished = 0;
10980
10981         printf("starting notify-bench test\n");
10982
10983         if (use_multishare_conn) {
10984                 char **unc_list;
10985                 unc_list = file_lines_load(multishare_conn_fname,
10986                                            &num_unc_names, 0, NULL);
10987                 if (!unc_list || num_unc_names <= 0) {
10988                         d_printf("Failed to load unc names list from '%s'\n",
10989                                  multishare_conn_fname);
10990                         return false;
10991                 }
10992                 TALLOC_FREE(unc_list);
10993         } else {
10994                 num_unc_names = 1;
10995         }
10996
10997         ev = samba_tevent_context_init(talloc_tos());
10998         if (ev == NULL) {
10999                 d_printf("tevent_context_init failed\n");
11000                 return false;
11001         }
11002
11003         for (i=0; i<num_unc_names; i++) {
11004                 struct cli_state *cli;
11005                 char *base_fname;
11006
11007                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11008                                              dname, i);
11009                 if (base_fname == NULL) {
11010                         return false;
11011                 }
11012
11013                 if (!torture_open_connection(&cli, i)) {
11014                         return false;
11015                 }
11016
11017                 status = cli_ntcreate(cli, dname, 0,
11018                                       MAXIMUM_ALLOWED_ACCESS,
11019                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11020                                       FILE_SHARE_DELETE,
11021                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11022                                       &dnum, NULL);
11023
11024                 if (!NT_STATUS_IS_OK(status)) {
11025                         d_printf("Could not create %s: %s\n", dname,
11026                                  nt_errstr(status));
11027                         return false;
11028                 }
11029
11030                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11031                                            FILE_NOTIFY_CHANGE_FILE_NAME |
11032                                            FILE_NOTIFY_CHANGE_DIR_NAME |
11033                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
11034                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
11035                                            false, print_notifies, NULL);
11036                 if (req1 == NULL) {
11037                         d_printf("Could not create notify request\n");
11038                         return false;
11039                 }
11040
11041                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11042                                                base_fname, 10, torture_numops);
11043                 if (req2 == NULL) {
11044                         d_printf("Could not create createdels request\n");
11045                         return false;
11046                 }
11047                 TALLOC_FREE(base_fname);
11048
11049                 tevent_req_set_callback(req2, notify_bench_done,
11050                                         &num_finished);
11051         }
11052
11053         while (num_finished < num_unc_names) {
11054                 int ret;
11055                 ret = tevent_loop_once(ev);
11056                 if (ret != 0) {
11057                         d_printf("tevent_loop_once failed\n");
11058                         return false;
11059                 }
11060         }
11061
11062         if (!tevent_req_poll(req2, ev)) {
11063                 d_printf("tevent_req_poll failed\n");
11064         }
11065
11066         status = torture_createdels_recv(req2);
11067         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11068
11069         return true;
11070 }
11071
11072 static bool run_mangle1(int dummy)
11073 {
11074         struct cli_state *cli;
11075         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11076         uint16_t fnum;
11077         fstring alt_name;
11078         NTSTATUS status;
11079
11080         printf("starting mangle1 test\n");
11081         if (!torture_open_connection(&cli, 0)) {
11082                 return False;
11083         }
11084
11085         smbXcli_conn_set_sockopt(cli->conn, sockops);
11086
11087         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11088                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11089                               0, 0, &fnum, NULL);
11090         if (!NT_STATUS_IS_OK(status)) {
11091                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11092                 return false;
11093         }
11094         cli_close(cli, fnum);
11095
11096         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11097         if (!NT_STATUS_IS_OK(status)) {
11098                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11099                          nt_errstr(status));
11100                 return false;
11101         }
11102         d_printf("alt_name: %s\n", alt_name);
11103
11104         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11105         if (!NT_STATUS_IS_OK(status)) {
11106                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11107                          nt_errstr(status));
11108                 return false;
11109         }
11110         cli_close(cli, fnum);
11111
11112         status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11113         if (!NT_STATUS_IS_OK(status)) {
11114                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11115                          nt_errstr(status));
11116                 return false;
11117         }
11118
11119         return true;
11120 }
11121
11122 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11123                                                  const char *mask,
11124                                                  void *state)
11125 {
11126         if (f->short_name == NULL) {
11127                 return NT_STATUS_OK;
11128         }
11129
11130         if (strlen(f->short_name) == 0) {
11131                 return NT_STATUS_OK;
11132         }
11133
11134         printf("unexpected shortname: %s\n", f->short_name);
11135
11136         return NT_STATUS_OBJECT_NAME_INVALID;
11137 }
11138
11139 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11140                                             const char *mask,
11141                                             void *state)
11142 {
11143         char *name = state;
11144
11145         printf("name: %s\n", f->name);
11146         fstrcpy(name, f->name);
11147         return NT_STATUS_OK;
11148 }
11149
11150 static bool run_mangle_illegal(int dummy)
11151 {
11152         struct cli_state *cli = NULL;
11153         struct cli_state *cli_posix = NULL;
11154         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11155         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11156         char *mangled_path = NULL;
11157         uint16_t fnum;
11158         fstring name;
11159         fstring alt_name;
11160         NTSTATUS status;
11161
11162         printf("starting mangle-illegal test\n");
11163
11164         if (!torture_open_connection(&cli, 0)) {
11165                 return False;
11166         }
11167
11168         smbXcli_conn_set_sockopt(cli->conn, sockops);
11169
11170         if (!torture_open_connection(&cli_posix, 0)) {
11171                 return false;
11172         }
11173
11174         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11175
11176         status = torture_setup_unix_extensions(cli_posix);
11177         if (!NT_STATUS_IS_OK(status)) {
11178                 return false;
11179         }
11180
11181         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11182         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11183         if (!NT_STATUS_IS_OK(status)) {
11184                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11185                 return False;
11186         }
11187
11188         /*
11189          * Create a file with illegal NTFS characters and test that we
11190          * get a usable mangled name
11191          */
11192
11193         cli_setatr(cli_posix, illegal_fname, 0, 0);
11194         cli_posix_unlink(cli_posix, illegal_fname);
11195
11196         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11197                                 0600, &fnum);
11198         if (!NT_STATUS_IS_OK(status)) {
11199                 printf("POSIX create of %s failed (%s)\n",
11200                        illegal_fname, nt_errstr(status));
11201                 return false;
11202         }
11203
11204         status = cli_close(cli_posix, fnum);
11205         if (!NT_STATUS_IS_OK(status)) {
11206                 printf("close failed (%s)\n", nt_errstr(status));
11207                 return false;
11208         }
11209
11210         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11211         if (!NT_STATUS_IS_OK(status)) {
11212                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11213                 return false;
11214         }
11215
11216         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11217         if (mangled_path == NULL) {
11218                 return false;
11219         }
11220
11221         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11222         if (!NT_STATUS_IS_OK(status)) {
11223                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11224                 TALLOC_FREE(mangled_path);
11225                 return false;
11226         }
11227         TALLOC_FREE(mangled_path);
11228         cli_close(cli, fnum);
11229
11230         cli_setatr(cli_posix, illegal_fname, 0, 0);
11231         cli_posix_unlink(cli_posix, illegal_fname);
11232
11233         /*
11234          * Create a file with a long name and check that we got *no* short name.
11235          */
11236
11237         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11238                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11239                               0, 0, &fnum, NULL);
11240         if (!NT_STATUS_IS_OK(status)) {
11241                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11242                 return false;
11243         }
11244         cli_close(cli, fnum);
11245
11246         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11247         if (!NT_STATUS_IS_OK(status)) {
11248                 d_printf("cli_list failed\n");
11249                 return false;
11250         }
11251
11252         cli_unlink(cli, fname, 0);
11253         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11254
11255         if (!torture_close_connection(cli_posix)) {
11256                 return false;
11257         }
11258
11259         if (!torture_close_connection(cli)) {
11260                 return false;
11261         }
11262
11263         return true;
11264 }
11265
11266 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11267 {
11268         size_t *to_pull = (size_t *)priv;
11269         size_t thistime = *to_pull;
11270
11271         thistime = MIN(thistime, n);
11272         if (thistime == 0) {
11273                 return 0;
11274         }
11275
11276         memset(buf, 0, thistime);
11277         *to_pull -= thistime;
11278         return thistime;
11279 }
11280
11281 static bool run_windows_write(int dummy)
11282 {
11283         struct cli_state *cli1;
11284         uint16_t fnum;
11285         int i;
11286         bool ret = false;
11287         const char *fname = "\\writetest.txt";
11288         struct timeval start_time;
11289         double seconds;
11290         double kbytes;
11291         NTSTATUS status;
11292
11293         printf("starting windows_write test\n");
11294         if (!torture_open_connection(&cli1, 0)) {
11295                 return False;
11296         }
11297
11298         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11299         if (!NT_STATUS_IS_OK(status)) {
11300                 printf("open failed (%s)\n", nt_errstr(status));
11301                 return False;
11302         }
11303
11304         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11305
11306         start_time = timeval_current();
11307
11308         for (i=0; i<torture_numops; i++) {
11309                 uint8_t c = 0;
11310                 off_t start = i * torture_blocksize;
11311                 size_t to_pull = torture_blocksize - 1;
11312
11313                 status = cli_writeall(cli1, fnum, 0, &c,
11314                                       start + torture_blocksize - 1, 1, NULL);
11315                 if (!NT_STATUS_IS_OK(status)) {
11316                         printf("cli_write failed: %s\n", nt_errstr(status));
11317                         goto fail;
11318                 }
11319
11320                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11321                                   null_source, &to_pull);
11322                 if (!NT_STATUS_IS_OK(status)) {
11323                         printf("cli_push returned: %s\n", nt_errstr(status));
11324                         goto fail;
11325                 }
11326         }
11327
11328         seconds = timeval_elapsed(&start_time);
11329         kbytes = (double)torture_blocksize * torture_numops;
11330         kbytes /= 1024;
11331
11332         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11333                (double)seconds, (int)(kbytes/seconds));
11334
11335         ret = true;
11336  fail:
11337         cli_close(cli1, fnum);
11338         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11339         torture_close_connection(cli1);
11340         return ret;
11341 }
11342
11343 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11344 {
11345         size_t max_pdu = 0x1FFFF;
11346
11347         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11348                 max_pdu = 0xFFFFFF;
11349         }
11350
11351         if (smb1cli_conn_signing_is_active(cli->conn)) {
11352                 max_pdu = 0x1FFFF;
11353         }
11354
11355         if (smb1cli_conn_encryption_on(cli->conn)) {
11356                 max_pdu = CLI_BUFFER_SIZE;
11357         }
11358
11359         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11360                 len_requested &= 0xFFFF;
11361         }
11362
11363         return MIN(len_requested,
11364                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11365 }
11366
11367 static bool check_read_call(struct cli_state *cli,
11368                             uint16_t fnum,
11369                             uint8_t *buf,
11370                             size_t len_requested)
11371 {
11372         NTSTATUS status;
11373         struct tevent_req *subreq = NULL;
11374         ssize_t len_read = 0;
11375         size_t len_expected = 0;
11376         struct tevent_context *ev = NULL;
11377
11378         ev = samba_tevent_context_init(talloc_tos());
11379         if (ev == NULL) {
11380                 return false;
11381         }
11382
11383         subreq = cli_read_andx_send(talloc_tos(),
11384                                     ev,
11385                                     cli,
11386                                     fnum,
11387                                     0,
11388                                     len_requested);
11389
11390         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11391                 return false;
11392         }
11393
11394         status = cli_read_andx_recv(subreq, &len_read, &buf);
11395         if (!NT_STATUS_IS_OK(status)) {
11396                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11397                 return false;
11398         }
11399
11400         TALLOC_FREE(subreq);
11401         TALLOC_FREE(ev);
11402
11403         len_expected = calc_expected_return(cli, len_requested);
11404
11405         if (len_expected > 0x10000 && len_read == 0x10000) {
11406                 /* Windows servers only return a max of 0x10000,
11407                    doesn't matter if you set CAP_LARGE_READX in
11408                    the client sessionsetupX call or not. */
11409                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11410                         (unsigned int)len_requested);
11411         } else if (len_read != len_expected) {
11412                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11413                         (unsigned int)len_requested,
11414                         (unsigned int)len_read,
11415                         (unsigned int)len_expected);
11416                 return false;
11417         } else {
11418                 d_printf("Correct read reply.\n");
11419         }
11420
11421         return true;
11422 }
11423
11424 /* Test large readX variants. */
11425 static bool large_readx_tests(struct cli_state *cli,
11426                                 uint16_t fnum,
11427                                 uint8_t *buf)
11428 {
11429         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11430         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11431                 return false;
11432         }
11433         /* A read of 0x10000 should return 0x10000 bytes. */
11434         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11435                 return false;
11436         }
11437         /* A read of 0x10000 should return 0x10001 bytes. */
11438         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11439                 return false;
11440         }
11441         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11442            the requested number of bytes. */
11443         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11444                 return false;
11445         }
11446         /* A read of 1MB should return 1MB bytes (on Samba). */
11447         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11448                 return false;
11449         }
11450
11451         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11452                 return false;
11453         }
11454         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11455                 return false;
11456         }
11457         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11458                 return false;
11459         }
11460         return true;
11461 }
11462
11463 static bool run_large_readx(int dummy)
11464 {
11465         uint8_t *buf = NULL;
11466         struct cli_state *cli1 = NULL;
11467         struct cli_state *cli2 = NULL;
11468         bool correct = false;
11469         const char *fname = "\\large_readx.dat";
11470         NTSTATUS status;
11471         uint16_t fnum1 = UINT16_MAX;
11472         uint32_t normal_caps = 0;
11473         size_t file_size = 20*1024*1024;
11474         TALLOC_CTX *frame = talloc_stackframe();
11475         size_t i;
11476         struct {
11477                 const char *name;
11478                 enum smb_signing_setting signing_setting;
11479                 enum protocol_types protocol;
11480         } runs[] = {
11481                 {
11482                         .name = "NT1",
11483                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11484                         .protocol = PROTOCOL_NT1,
11485                 },{
11486                         .name = "NT1 - SIGNING_REQUIRED",
11487                         .signing_setting = SMB_SIGNING_REQUIRED,
11488                         .protocol = PROTOCOL_NT1,
11489                 },
11490         };
11491
11492         printf("starting large_readx test\n");
11493
11494         if (!torture_open_connection(&cli1, 0)) {
11495                 goto out;
11496         }
11497
11498         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11499
11500         if (!(normal_caps & CAP_LARGE_READX)) {
11501                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11502                         (unsigned int)normal_caps);
11503                 goto out;
11504         }
11505
11506         /* Create a file of size 4MB. */
11507         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11508                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11509                         0, 0, &fnum1, NULL);
11510
11511         if (!NT_STATUS_IS_OK(status)) {
11512                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11513                 goto out;
11514         }
11515
11516         /* Write file_size bytes. */
11517         buf = talloc_zero_array(frame, uint8_t, file_size);
11518         if (buf == NULL) {
11519                 goto out;
11520         }
11521
11522         status = cli_writeall(cli1,
11523                               fnum1,
11524                               0,
11525                               buf,
11526                               0,
11527                               file_size,
11528                               NULL);
11529         if (!NT_STATUS_IS_OK(status)) {
11530                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11531                 goto out;
11532         }
11533
11534         status = cli_close(cli1, fnum1);
11535         if (!NT_STATUS_IS_OK(status)) {
11536                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11537                 goto out;
11538         }
11539
11540         fnum1 = UINT16_MAX;
11541
11542         for (i=0; i < ARRAY_SIZE(runs); i++) {
11543                 enum smb_signing_setting saved_signing_setting = signing_state;
11544                 uint16_t fnum2 = -1;
11545
11546                 if (do_encrypt &&
11547                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11548                 {
11549                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11550                         continue;
11551                 }
11552
11553                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11554
11555                 signing_state = runs[i].signing_setting;
11556                 cli2 = open_nbt_connection();
11557                 signing_state = saved_signing_setting;
11558                 if (cli2 == NULL) {
11559                         goto out;
11560                 }
11561
11562                 status = smbXcli_negprot(cli2->conn,
11563                                          cli2->timeout,
11564                                          runs[i].protocol,
11565                                          runs[i].protocol,
11566                                          NULL,
11567                                          NULL,
11568                                          NULL);
11569                 if (!NT_STATUS_IS_OK(status)) {
11570                         goto out;
11571                 }
11572
11573                 status = cli_session_setup_creds(cli2, torture_creds);
11574                 if (!NT_STATUS_IS_OK(status)) {
11575                         goto out;
11576                 }
11577
11578                 status = cli_tree_connect(cli2,
11579                                         share,
11580                                         "?????",
11581                                         password);
11582                 if (!NT_STATUS_IS_OK(status)) {
11583                         goto out;
11584                 }
11585
11586                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11587
11588                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11589
11590                 if (!(normal_caps & CAP_LARGE_READX)) {
11591                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11592                                 (unsigned int)normal_caps);
11593                         goto out;
11594                 }
11595
11596                 if (do_encrypt) {
11597                         if (force_cli_encryption(cli2, share) == false) {
11598                                 goto out;
11599                         }
11600                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11601                         uint16_t major, minor;
11602                         uint32_t caplow, caphigh;
11603
11604                         status = cli_unix_extensions_version(cli2,
11605                                                              &major, &minor,
11606                                                              &caplow, &caphigh);
11607                         if (!NT_STATUS_IS_OK(status)) {
11608                                 goto out;
11609                         }
11610                 }
11611
11612                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11613                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11614                                 0, 0, &fnum2, NULL);
11615                 if (!NT_STATUS_IS_OK(status)) {
11616                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11617                         goto out;
11618                 }
11619
11620                 /* All reads must return less than file_size bytes. */
11621                 if (!large_readx_tests(cli2, fnum2, buf)) {
11622                         goto out;
11623                 }
11624
11625                 status = cli_close(cli2, fnum2);
11626                 if (!NT_STATUS_IS_OK(status)) {
11627                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11628                         goto out;
11629                 }
11630                 fnum2 = -1;
11631
11632                 if (!torture_close_connection(cli2)) {
11633                         goto out;
11634                 }
11635                 cli2 = NULL;
11636         }
11637
11638         correct = true;
11639         printf("Success on large_readx test\n");
11640
11641   out:
11642
11643         if (cli2) {
11644                 if (!torture_close_connection(cli2)) {
11645                         correct = false;
11646                 }
11647         }
11648
11649         if (cli1) {
11650                 if (fnum1 != UINT16_MAX) {
11651                         status = cli_close(cli1, fnum1);
11652                         if (!NT_STATUS_IS_OK(status)) {
11653                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11654                         }
11655                         fnum1 = UINT16_MAX;
11656                 }
11657
11658                 status = cli_unlink(cli1, fname,
11659                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11660                 if (!NT_STATUS_IS_OK(status)) {
11661                         printf("unlink failed (%s)\n", nt_errstr(status));
11662                 }
11663
11664                 if (!torture_close_connection(cli1)) {
11665                         correct = false;
11666                 }
11667         }
11668
11669         TALLOC_FREE(frame);
11670
11671         printf("finished large_readx test\n");
11672         return correct;
11673 }
11674
11675 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11676                                   const char *mask,
11677                                   void *private_data)
11678 {
11679         uint32_t *p_attr = (uint32_t *)private_data;
11680
11681         if (strequal(finfo->name, test_filename)) {
11682                 *p_attr = finfo->attr;
11683         }
11684
11685         return NT_STATUS_OK;
11686 }
11687
11688 static bool run_msdfs_attribute(int dummy)
11689 {
11690         static struct cli_state *cli;
11691         bool correct = false;
11692         uint32_t attr = 0;
11693         NTSTATUS status;
11694
11695         printf("Starting MSDFS-ATTRIBUTE test\n");
11696
11697         if (test_filename == NULL || test_filename[0] == '\0') {
11698                 printf("MSDFS-ATTRIBUTE test "
11699                         "needs -f filename-of-msdfs-link\n");
11700                 return false;
11701         }
11702
11703         /*
11704          * NB. We use torture_open_connection_flags() not
11705          * torture_open_connection() as the latter forces
11706          * SMB1.
11707          */
11708         if (!torture_open_connection_flags(&cli, 0, 0)) {
11709                 return false;
11710         }
11711
11712         smbXcli_conn_set_sockopt(cli->conn, sockops);
11713
11714         status = cli_list(cli,
11715                         "*",
11716                         FILE_ATTRIBUTE_DIRECTORY,
11717                         msdfs_attribute_list_fn,
11718                         &attr);
11719
11720         if (!NT_STATUS_IS_OK(status)) {
11721                 printf("cli_list failed with %s\n",
11722                         nt_errstr(status));
11723                 goto out;
11724         }
11725         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11726                 printf("file %s should have "
11727                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11728                         test_filename,
11729                         (unsigned int)attr);
11730                 goto out;
11731         }
11732
11733         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11734                 printf("file %s should have "
11735                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11736                         test_filename,
11737                         (unsigned int)attr);
11738                 goto out;
11739         }
11740
11741         correct = true;
11742
11743   out:
11744
11745         torture_close_connection(cli);
11746         return correct;
11747 }
11748
11749 static bool run_cli_echo(int dummy)
11750 {
11751         struct cli_state *cli;
11752         NTSTATUS status;
11753
11754         printf("starting cli_echo test\n");
11755         if (!torture_open_connection(&cli, 0)) {
11756                 return false;
11757         }
11758         smbXcli_conn_set_sockopt(cli->conn, sockops);
11759
11760         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11761
11762         d_printf("cli_echo returned %s\n", nt_errstr(status));
11763
11764         torture_close_connection(cli);
11765         return NT_STATUS_IS_OK(status);
11766 }
11767
11768 static int splice_status(off_t written, void *priv)
11769 {
11770         return true;
11771 }
11772
11773 static bool run_cli_splice(int dummy)
11774 {
11775         uint8_t *buf = NULL;
11776         struct cli_state *cli1 = NULL;
11777         bool correct = false;
11778         const char *fname_src = "\\splice_src.dat";
11779         const char *fname_dst = "\\splice_dst.dat";
11780         NTSTATUS status;
11781         uint16_t fnum1 = UINT16_MAX;
11782         uint16_t fnum2 = UINT16_MAX;
11783         size_t file_size = 2*1024*1024;
11784         size_t splice_size = 1*1024*1024 + 713;
11785         uint8_t digest1[16], digest2[16];
11786         off_t written = 0;
11787         size_t nread = 0;
11788         TALLOC_CTX *frame = talloc_stackframe();
11789
11790         printf("starting cli_splice test\n");
11791
11792         if (!torture_open_connection(&cli1, 0)) {
11793                 goto out;
11794         }
11795
11796         cli_unlink(cli1, fname_src,
11797                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11798         cli_unlink(cli1, fname_dst,
11799                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11800
11801         /* Create a file */
11802         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11803                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11804                         0, 0, &fnum1, NULL);
11805
11806         if (!NT_STATUS_IS_OK(status)) {
11807                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11808                 goto out;
11809         }
11810
11811         /* Write file_size bytes - must be bigger than splice_size. */
11812         buf = talloc_zero_array(frame, uint8_t, file_size);
11813         if (buf == NULL) {
11814                 d_printf("talloc_fail\n");
11815                 goto out;
11816         }
11817
11818         /* Fill it with random numbers. */
11819         generate_random_buffer(buf, file_size);
11820
11821         /* MD5 the first 1MB + 713 bytes. */
11822         gnutls_hash_fast(GNUTLS_DIG_MD5,
11823                          buf,
11824                          splice_size,
11825                          digest1);
11826
11827         status = cli_writeall(cli1,
11828                               fnum1,
11829                               0,
11830                               buf,
11831                               0,
11832                               file_size,
11833                               NULL);
11834         if (!NT_STATUS_IS_OK(status)) {
11835                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11836                 goto out;
11837         }
11838
11839         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11840                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11841                         0, 0, &fnum2, NULL);
11842
11843         if (!NT_STATUS_IS_OK(status)) {
11844                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11845                 goto out;
11846         }
11847
11848         /* Now splice 1MB + 713 bytes. */
11849         status = cli_splice(cli1,
11850                                 cli1,
11851                                 fnum1,
11852                                 fnum2,
11853                                 splice_size,
11854                                 0,
11855                                 0,
11856                                 &written,
11857                                 splice_status,
11858                                 NULL);
11859
11860         if (!NT_STATUS_IS_OK(status)) {
11861                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11862                 goto out;
11863         }
11864
11865         /* Clear the old buffer. */
11866         memset(buf, '\0', file_size);
11867
11868         /* Read the new file. */
11869         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11870         if (!NT_STATUS_IS_OK(status)) {
11871                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11872                 goto out;
11873         }
11874         if (nread != splice_size) {
11875                 d_printf("bad read of 0x%x, should be 0x%x\n",
11876                         (unsigned int)nread,
11877                         (unsigned int)splice_size);
11878                 goto out;
11879         }
11880
11881         /* MD5 the first 1MB + 713 bytes. */
11882         gnutls_hash_fast(GNUTLS_DIG_MD5,
11883                          buf,
11884                          splice_size,
11885                          digest2);
11886
11887         /* Must be the same. */
11888         if (memcmp(digest1, digest2, 16) != 0) {
11889                 d_printf("bad MD5 compare\n");
11890                 goto out;
11891         }
11892
11893         correct = true;
11894         printf("Success on cli_splice test\n");
11895
11896   out:
11897
11898         if (cli1) {
11899                 if (fnum1 != UINT16_MAX) {
11900                         cli_close(cli1, fnum1);
11901                 }
11902                 if (fnum2 != UINT16_MAX) {
11903                         cli_close(cli1, fnum2);
11904                 }
11905
11906                 cli_unlink(cli1, fname_src,
11907                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11908                 cli_unlink(cli1, fname_dst,
11909                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11910
11911                 if (!torture_close_connection(cli1)) {
11912                         correct = false;
11913                 }
11914         }
11915
11916         TALLOC_FREE(frame);
11917         return correct;
11918 }
11919
11920 static bool run_uid_regression_test(int dummy)
11921 {
11922         static struct cli_state *cli;
11923         int16_t old_vuid;
11924         int32_t old_cnum;
11925         bool correct = True;
11926         struct smbXcli_tcon *tcon_copy = NULL;
11927         NTSTATUS status;
11928
11929         printf("starting uid regression test\n");
11930
11931         if (!torture_open_connection(&cli, 0)) {
11932                 return False;
11933         }
11934
11935         smbXcli_conn_set_sockopt(cli->conn, sockops);
11936
11937         /* Ok - now save then logoff our current user. */
11938         old_vuid = cli_state_get_uid(cli);
11939
11940         status = cli_ulogoff(cli);
11941         if (!NT_STATUS_IS_OK(status)) {
11942                 d_printf("(%s) cli_ulogoff failed: %s\n",
11943                          __location__, nt_errstr(status));
11944                 correct = false;
11945                 goto out;
11946         }
11947
11948         cli_state_set_uid(cli, old_vuid);
11949
11950         /* Try an operation. */
11951         status = cli_mkdir(cli, "\\uid_reg_test");
11952         if (NT_STATUS_IS_OK(status)) {
11953                 d_printf("(%s) cli_mkdir succeeded\n",
11954                          __location__);
11955                 correct = false;
11956                 goto out;
11957         } else {
11958                 /* Should be bad uid. */
11959                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11960                                  NT_STATUS_USER_SESSION_DELETED)) {
11961                         correct = false;
11962                         goto out;
11963                 }
11964         }
11965
11966         old_cnum = cli_state_get_tid(cli);
11967         /*
11968          * This is an SMB1-only test.
11969          * Copy the tcon, not "save/restore".
11970          *
11971          * In SMB1 the cli_tdis() below frees
11972          * cli->smb1.tcon so we need a copy
11973          * of the struct to put back for the
11974          * second tdis call with invalid vuid.
11975          *
11976          * This is a test-only hack. Real client code
11977          * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11978          */
11979         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11980         if (tcon_copy == NULL) {
11981                 correct = false;
11982                 goto out;
11983         }
11984
11985         /* Now try a SMBtdis with the invalid vuid set to zero. */
11986         cli_state_set_uid(cli, 0);
11987
11988         /* This should succeed. */
11989         status = cli_tdis(cli);
11990
11991         if (NT_STATUS_IS_OK(status)) {
11992                 d_printf("First tdis with invalid vuid should succeed.\n");
11993         } else {
11994                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11995                 correct = false;
11996                 cli->smb1.tcon = tcon_copy;
11997                 goto out;
11998         }
11999
12000         cli->smb1.tcon = tcon_copy;
12001         cli_state_set_uid(cli, old_vuid);
12002         cli_state_set_tid(cli, old_cnum);
12003
12004         /* This should fail. */
12005         status = cli_tdis(cli);
12006         if (NT_STATUS_IS_OK(status)) {
12007                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12008                 correct = false;
12009                 goto out;
12010         } else {
12011                 /* Should be bad tid. */
12012                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12013                                 NT_STATUS_NETWORK_NAME_DELETED)) {
12014                         correct = false;
12015                         goto out;
12016                 }
12017         }
12018
12019         cli_rmdir(cli, "\\uid_reg_test");
12020
12021   out:
12022
12023         cli_shutdown(cli);
12024         return correct;
12025 }
12026
12027
12028 static const char *illegal_chars = "*\\/?<>|\":";
12029 static char force_shortname_chars[] = " +,.[];=\177";
12030
12031 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12032                              const char *mask, void *state)
12033 {
12034         struct cli_state *pcli = (struct cli_state *)state;
12035         fstring fname;
12036         NTSTATUS status = NT_STATUS_OK;
12037
12038         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12039
12040         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12041                 return NT_STATUS_OK;
12042
12043         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12044                 status = cli_rmdir(pcli, fname);
12045                 if (!NT_STATUS_IS_OK(status)) {
12046                         printf("del_fn: failed to rmdir %s\n,", fname );
12047                 }
12048         } else {
12049                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12050                 if (!NT_STATUS_IS_OK(status)) {
12051                         printf("del_fn: failed to unlink %s\n,", fname );
12052                 }
12053         }
12054         return status;
12055 }
12056
12057 struct sn_state {
12058         int matched;
12059         int i;
12060         bool val;
12061 };
12062
12063 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12064                               const char *name, void *state)
12065 {
12066         struct sn_state *s = (struct sn_state  *)state;
12067         int i = s->i;
12068
12069 #if 0
12070         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12071                 i, finfo->name, finfo->short_name);
12072 #endif
12073
12074         if (strchr(force_shortname_chars, i)) {
12075                 if (!finfo->short_name) {
12076                         /* Shortname not created when it should be. */
12077                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12078                                 __location__, finfo->name, i);
12079                         s->val = true;
12080                 }
12081         } else if (finfo->short_name){
12082                 /* Shortname created when it should not be. */
12083                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12084                         __location__, finfo->short_name, finfo->name);
12085                 s->val = true;
12086         }
12087         s->matched += 1;
12088         return NT_STATUS_OK;
12089 }
12090
12091 static bool run_shortname_test(int dummy)
12092 {
12093         static struct cli_state *cli;
12094         bool correct = True;
12095         int i;
12096         struct sn_state s;
12097         char fname[40];
12098         NTSTATUS status;
12099
12100         printf("starting shortname test\n");
12101
12102         if (!torture_open_connection(&cli, 0)) {
12103                 return False;
12104         }
12105
12106         smbXcli_conn_set_sockopt(cli->conn, sockops);
12107
12108         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12109         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12110         cli_rmdir(cli, "\\shortname");
12111
12112         status = cli_mkdir(cli, "\\shortname");
12113         if (!NT_STATUS_IS_OK(status)) {
12114                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12115                         __location__, nt_errstr(status));
12116                 correct = false;
12117                 goto out;
12118         }
12119
12120         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12121                 correct = false;
12122                 goto out;
12123         }
12124         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12125                 correct = false;
12126                 goto out;
12127         }
12128
12129         s.val = false;
12130
12131         for (i = 32; i < 128; i++) {
12132                 uint16_t fnum = (uint16_t)-1;
12133
12134                 s.i = i;
12135
12136                 if (strchr(illegal_chars, i)) {
12137                         continue;
12138                 }
12139                 fname[15] = i;
12140
12141                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12142                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12143                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12144                 if (!NT_STATUS_IS_OK(status)) {
12145                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12146                                 __location__, fname, nt_errstr(status));
12147                         correct = false;
12148                         goto out;
12149                 }
12150                 cli_close(cli, fnum);
12151
12152                 s.matched = 0;
12153                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12154                                   shortname_list_fn, &s);
12155                 if (s.matched != 1) {
12156                         d_printf("(%s) failed to list %s: %s\n",
12157                                 __location__, fname, nt_errstr(status));
12158                         correct = false;
12159                         goto out;
12160                 }
12161
12162                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12163                 if (!NT_STATUS_IS_OK(status)) {
12164                         d_printf("(%s) failed to delete %s: %s\n",
12165                                 __location__, fname, nt_errstr(status));
12166                         correct = false;
12167                         goto out;
12168                 }
12169
12170                 if (s.val) {
12171                         correct = false;
12172                         goto out;
12173                 }
12174         }
12175
12176   out:
12177
12178         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12179         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12180         cli_rmdir(cli, "\\shortname");
12181         torture_close_connection(cli);
12182         return correct;
12183 }
12184
12185 TLDAPRC callback_code;
12186
12187 static void pagedsearch_cb(struct tevent_req *req)
12188 {
12189         TLDAPRC rc;
12190         struct tldap_message *msg;
12191         char *dn;
12192
12193         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12194         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12195                 d_printf("tldap_search_paged_recv failed: %s\n",
12196                          tldap_rc2string(rc));
12197                 callback_code = rc;
12198                 return;
12199         }
12200         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12201                 TALLOC_FREE(msg);
12202                 return;
12203         }
12204         if (!tldap_entry_dn(msg, &dn)) {
12205                 d_printf("tldap_entry_dn failed\n");
12206                 return;
12207         }
12208         d_printf("%s\n", dn);
12209         TALLOC_FREE(msg);
12210 }
12211
12212 enum tldap_extended_val {
12213         EXTENDED_ZERO = 0,
12214         EXTENDED_ONE = 1,
12215         EXTENDED_NONE = 2,
12216 };
12217
12218 /*
12219  * Construct an extended dn control with either no value, 0 or 1
12220  *
12221  * No value and 0 are equivalent (non-hyphenated GUID)
12222  * 1 has the hyphenated GUID
12223  */
12224 static struct tldap_control *
12225 tldap_build_extended_control(enum tldap_extended_val val)
12226 {
12227         struct tldap_control empty_control;
12228         struct asn1_data *data;
12229
12230         ZERO_STRUCT(empty_control);
12231
12232         if (val != EXTENDED_NONE) {
12233                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12234
12235                 if (!data) {
12236                         return NULL;
12237                 }
12238
12239                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12240                         return NULL;
12241                 }
12242
12243                 if (!asn1_write_Integer(data, (int)val)) {
12244                         return NULL;
12245                 }
12246
12247                 if (!asn1_pop_tag(data)) {
12248                         return NULL;
12249                 }
12250
12251                 if (!asn1_blob(data, &empty_control.value)) {
12252                         return NULL;
12253                 }
12254         }
12255
12256         empty_control.oid = "1.2.840.113556.1.4.529";
12257         empty_control.critical = true;
12258
12259         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12260
12261 }
12262
12263 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12264                                       enum tldap_extended_val control_val)
12265 {
12266         struct tldap_control *control = tldap_build_extended_control(control_val);
12267         char *dn = NULL;
12268         struct tldap_message **msg;
12269         TLDAPRC rc;
12270
12271         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12272                           "(objectClass=*)", NULL, 0, 0,
12273                           control, 1, NULL,
12274                           0, 0, 0, 0, talloc_tos(), &msg);
12275         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12276                 d_printf("tldap_search for domain DN failed: %s\n",
12277                          tldap_errstr(talloc_tos(), ld, rc));
12278                 return false;
12279         }
12280
12281         if (!tldap_entry_dn(msg[0], &dn)) {
12282                 d_printf("tldap_search domain DN fetch failed: %s\n",
12283                          tldap_errstr(talloc_tos(), ld, rc));
12284                 return false;
12285         }
12286
12287         d_printf("%s\n", dn);
12288         {
12289                 uint32_t time_low;
12290                 uint32_t time_mid, time_hi_and_version;
12291                 uint32_t clock_seq[2];
12292                 uint32_t node[6];
12293                 char next;
12294
12295                 switch (control_val) {
12296                 case EXTENDED_NONE:
12297                 case EXTENDED_ZERO:
12298                         /*
12299                          * When reading GUIDs with hyphens, scanf will treat
12300                          * hyphen as a hex character (and counts as part of the
12301                          * width). This creates leftover GUID string which we
12302                          * check will for with 'next' and closing '>'.
12303                          */
12304                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12305                                          &time_low, &time_mid,
12306                                          &time_hi_and_version, &clock_seq[0],
12307                                          &clock_seq[1], &node[0], &node[1],
12308                                          &node[2], &node[3], &node[4],
12309                                          &node[5], &next)) {
12310                                 /* This GUID is good */
12311                         } else {
12312                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12313                                 return false;
12314                         }
12315
12316                         break;
12317                 case EXTENDED_ONE:
12318                         if (12 == sscanf(dn,
12319                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12320                                          &time_low, &time_mid,
12321                                          &time_hi_and_version, &clock_seq[0],
12322                                          &clock_seq[1], &node[0], &node[1],
12323                                          &node[2], &node[3], &node[4],
12324                                          &node[5], &next)) {
12325                                 /* This GUID is good */
12326                         } else {
12327                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12328                                 return false;
12329                         }
12330
12331                         break;
12332                 default:
12333                         return false;
12334                 }
12335         }
12336
12337         return true;
12338 }
12339
12340 static bool run_tldap(int dummy)
12341 {
12342         struct tldap_context *ld;
12343         int fd;
12344         TLDAPRC rc;
12345         NTSTATUS status;
12346         struct sockaddr_storage addr;
12347         struct tevent_context *ev;
12348         struct tevent_req *req;
12349         char *basedn;
12350         const char *filter;
12351         struct loadparm_context *lp_ctx = NULL;
12352         int tcp_port = 389;
12353         bool use_tls = false;
12354         bool use_starttls = false;
12355         int wrap_flags = -1;
12356         uint32_t gensec_features = 0;
12357
12358         lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12359
12360         wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12361
12362         if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12363                 use_tls = true;
12364                 tcp_port = 636;
12365         } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12366                 use_tls = true;
12367                 use_starttls = true;
12368         }
12369         if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12370                 gensec_features |= GENSEC_FEATURE_SEAL;
12371         }
12372         if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12373                 gensec_features |= GENSEC_FEATURE_SIGN;
12374         }
12375
12376         if (gensec_features != 0) {
12377                 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12378         }
12379
12380         if (!resolve_name(host, &addr, 0, false)) {
12381                 d_printf("could not find host %s\n", host);
12382                 return false;
12383         }
12384         status = open_socket_out(&addr, tcp_port, 9999, &fd);
12385         if (!NT_STATUS_IS_OK(status)) {
12386                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12387                 return false;
12388         }
12389
12390         ld = tldap_context_create(talloc_tos(), fd);
12391         if (ld == NULL) {
12392                 close(fd);
12393                 d_printf("tldap_context_create failed\n");
12394                 return false;
12395         }
12396
12397         if (use_tls && !tldap_has_tls_tstream(ld)) {
12398                 tldap_set_starttls_needed(ld, use_starttls);
12399
12400                 rc = tldap_tls_connect(ld, lp_ctx, host);
12401                 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12402                         DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12403                                 host, tldap_errstr(talloc_tos(), ld, rc));
12404                         return false;
12405                 }
12406         }
12407
12408         rc = tldap_fetch_rootdse(ld);
12409         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12410                 d_printf("tldap_fetch_rootdse failed: %s\n",
12411                          tldap_errstr(talloc_tos(), ld, rc));
12412                 return false;
12413         }
12414
12415         basedn = tldap_talloc_single_attribute(
12416                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12417         if (basedn == NULL) {
12418                 d_printf("no defaultNamingContext\n");
12419                 return false;
12420         }
12421         d_printf("defaultNamingContext: %s\n", basedn);
12422
12423         ev = samba_tevent_context_init(talloc_tos());
12424         if (ev == NULL) {
12425                 d_printf("tevent_context_init failed\n");
12426                 return false;
12427         }
12428
12429         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12430                                lp_ctx, gensec_features);
12431         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12432                 d_printf("tldap_gensec_bind failed\n");
12433                 return false;
12434         }
12435
12436         callback_code = TLDAP_SUCCESS;
12437
12438         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12439                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12440                                       NULL, 0, 0,
12441                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12442         if (req == NULL) {
12443                 d_printf("tldap_search_paged_send failed\n");
12444                 return false;
12445         }
12446         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12447
12448         tevent_req_poll(req, ev);
12449
12450         TALLOC_FREE(req);
12451
12452         rc = callback_code;
12453
12454         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12455                 d_printf("tldap_search with paging failed: %s\n",
12456                          tldap_errstr(talloc_tos(), ld, rc));
12457                 return false;
12458         }
12459
12460         /* test search filters against rootDSE */
12461         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12462                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12463
12464         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12465                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12466                           talloc_tos(), NULL);
12467         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12468                 d_printf("tldap_search with complex filter failed: %s\n",
12469                          tldap_errstr(talloc_tos(), ld, rc));
12470                 return false;
12471         }
12472
12473         /*
12474          * Tests to check for regression of:
12475          *
12476          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12477          *
12478          * TLDAP used here to pick apart the original string DN (with GUID)
12479          */
12480         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12481                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12482                          tldap_errstr(talloc_tos(), ld, rc));
12483                 return false;
12484         }
12485         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12486                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12487                          tldap_errstr(talloc_tos(), ld, rc));
12488                 return false;
12489         }
12490         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12491                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12492                          tldap_errstr(talloc_tos(), ld, rc));
12493                 return false;
12494         }
12495
12496         TALLOC_FREE(ld);
12497         return true;
12498 }
12499
12500 /* Torture test to ensure no regression of :
12501 https://bugzilla.samba.org/show_bug.cgi?id=7084
12502 */
12503
12504 static bool run_dir_createtime(int dummy)
12505 {
12506         struct cli_state *cli;
12507         const char *dname = "\\testdir_createtime";
12508         const char *fname = "\\testdir_createtime\\testfile";
12509         NTSTATUS status;
12510         struct timespec create_time;
12511         struct timespec create_time1;
12512         uint16_t fnum;
12513         bool ret = false;
12514         uint64_t ino;
12515
12516         if (!torture_open_connection(&cli, 0)) {
12517                 return false;
12518         }
12519
12520         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12521                 /* Ensure ino is zero, SMB2 gets a real one. */
12522                 ino = 0;
12523         } else {
12524                 /* Ensure ino is -1, SMB1 never gets a real one. */
12525                 ino = (uint64_t)-1;
12526         }
12527
12528         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12529         cli_rmdir(cli, dname);
12530
12531         status = cli_mkdir(cli, dname);
12532         if (!NT_STATUS_IS_OK(status)) {
12533                 printf("mkdir failed: %s\n", nt_errstr(status));
12534                 goto out;
12535         }
12536
12537         status = cli_qpathinfo2(cli,
12538                                 dname,
12539                                 &create_time,
12540                                 NULL,
12541                                 NULL,
12542                                 NULL,
12543                                 NULL,
12544                                 NULL,
12545                                 &ino,
12546                                 NULL);
12547         if (!NT_STATUS_IS_OK(status)) {
12548                 printf("cli_qpathinfo2 returned %s\n",
12549                        nt_errstr(status));
12550                 goto out;
12551         }
12552
12553         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12554                 /* SMB2 should always return an inode. */
12555                 if (ino == 0) {
12556                         printf("SMB2 bad inode (0)\n");
12557                         goto out;
12558                 }
12559         } else {
12560                 /* SMB1 must always return zero here. */
12561                 if (ino != 0) {
12562                         printf("SMB1 bad inode (!0)\n");
12563                         goto out;
12564                 }
12565         }
12566
12567         /* Sleep 3 seconds, then create a file. */
12568         sleep(3);
12569
12570         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12571                          DENY_NONE, &fnum);
12572         if (!NT_STATUS_IS_OK(status)) {
12573                 printf("cli_openx failed: %s\n", nt_errstr(status));
12574                 goto out;
12575         }
12576
12577         status = cli_qpathinfo2(cli,
12578                                 dname,
12579                                 &create_time1,
12580                                 NULL,
12581                                 NULL,
12582                                 NULL,
12583                                 NULL,
12584                                 NULL,
12585                                 NULL,
12586                                 NULL);
12587         if (!NT_STATUS_IS_OK(status)) {
12588                 printf("cli_qpathinfo2 (2) returned %s\n",
12589                        nt_errstr(status));
12590                 goto out;
12591         }
12592
12593         if (timespec_compare(&create_time1, &create_time)) {
12594                 printf("run_dir_createtime: create time was updated (error)\n");
12595         } else {
12596                 printf("run_dir_createtime: create time was not updated (correct)\n");
12597                 ret = true;
12598         }
12599
12600   out:
12601
12602         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12603         cli_rmdir(cli, dname);
12604         if (!torture_close_connection(cli)) {
12605                 ret = false;
12606         }
12607         return ret;
12608 }
12609
12610
12611 static bool run_streamerror(int dummy)
12612 {
12613         struct cli_state *cli;
12614         const char *dname = "\\testdir_streamerror";
12615         const char *streamname =
12616                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12617         NTSTATUS status;
12618         time_t change_time, access_time, write_time;
12619         off_t size;
12620         uint16_t fnum;
12621         uint32_t attr;
12622         bool ret = true;
12623
12624         if (!torture_open_connection(&cli, 0)) {
12625                 return false;
12626         }
12627
12628         torture_deltree(cli, dname);
12629
12630         status = cli_mkdir(cli, dname);
12631         if (!NT_STATUS_IS_OK(status)) {
12632                 printf("mkdir failed: %s\n", nt_errstr(status));
12633                 return false;
12634         }
12635
12636         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12637                                 &write_time, &size, &attr);
12638         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12639                 printf("pathinfo returned %s, expected "
12640                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12641                        nt_errstr(status));
12642                 ret = false;
12643         }
12644
12645         status = cli_ntcreate(cli, streamname, 0x16,
12646                               FILE_READ_DATA|FILE_READ_EA|
12647                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12648                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12649                               FILE_OPEN, 0, 0, &fnum, NULL);
12650
12651         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12652                 printf("ntcreate returned %s, expected "
12653                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12654                        nt_errstr(status));
12655                 ret = false;
12656         }
12657
12658
12659         cli_rmdir(cli, dname);
12660         return ret;
12661 }
12662
12663 struct pidtest_state {
12664         bool success;
12665         uint16_t vwv[1];
12666         DATA_BLOB data;
12667 };
12668
12669 static void pid_echo_done(struct tevent_req *subreq);
12670
12671 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12672                         struct tevent_context *ev,
12673                         struct cli_state *cli)
12674 {
12675         struct tevent_req *req, *subreq;
12676         struct pidtest_state *state;
12677
12678         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12679         if (req == NULL) {
12680                 return NULL;
12681         }
12682
12683         SSVAL(state->vwv, 0, 1);
12684         state->data = data_blob_const("hello", 5);
12685
12686         subreq = smb1cli_req_send(state,
12687                                 ev,
12688                                 cli->conn,
12689                                 SMBecho,
12690                                 0, 0, /* *_flags */
12691                                 0, 0, /* *_flags2 */
12692                                 cli->timeout,
12693                                 0xDEADBEEF, /* pid */
12694                                 NULL, /* tcon */
12695                                 NULL, /* session */
12696                                 ARRAY_SIZE(state->vwv), state->vwv,
12697                                 state->data.length, state->data.data);
12698
12699         if (tevent_req_nomem(subreq, req)) {
12700                 return tevent_req_post(req, ev);
12701         }
12702         tevent_req_set_callback(subreq, pid_echo_done, req);
12703         return req;
12704 }
12705
12706 static void pid_echo_done(struct tevent_req *subreq)
12707 {
12708         struct tevent_req *req = tevent_req_callback_data(
12709                 subreq, struct tevent_req);
12710         struct pidtest_state *state = tevent_req_data(
12711                 req, struct pidtest_state);
12712         NTSTATUS status;
12713         uint32_t num_bytes;
12714         uint8_t *bytes = NULL;
12715         struct iovec *recv_iov = NULL;
12716         uint8_t *phdr = NULL;
12717         uint16_t pidlow = 0;
12718         uint16_t pidhigh = 0;
12719         struct smb1cli_req_expected_response expected[] = {
12720         {
12721                 .status = NT_STATUS_OK,
12722                 .wct    = 1,
12723         },
12724         };
12725
12726         status = smb1cli_req_recv(subreq, state,
12727                                 &recv_iov,
12728                                 &phdr,
12729                                 NULL, /* pwct */
12730                                 NULL, /* pvwv */
12731                                 NULL, /* pvwv_offset */
12732                                 &num_bytes,
12733                                 &bytes,
12734                                 NULL, /* pbytes_offset */
12735                                 NULL, /* pinbuf */
12736                                 expected, ARRAY_SIZE(expected));
12737
12738         TALLOC_FREE(subreq);
12739
12740         if (!NT_STATUS_IS_OK(status)) {
12741                 tevent_req_nterror(req, status);
12742                 return;
12743         }
12744
12745         if (num_bytes != state->data.length) {
12746                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12747                 return;
12748         }
12749
12750         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12751                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12752                 return;
12753         }
12754
12755         /* Check pid low/high == DEADBEEF */
12756         pidlow = SVAL(phdr, HDR_PID);
12757         if (pidlow != 0xBEEF){
12758                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12759                         (unsigned int)pidlow);
12760                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12761                 return;
12762         }
12763         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12764         if (pidhigh != 0xDEAD){
12765                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12766                         (unsigned int)pidhigh);
12767                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12768                 return;
12769         }
12770
12771         tevent_req_done(req);
12772 }
12773
12774 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12775 {
12776         return tevent_req_simple_recv_ntstatus(req);
12777 }
12778
12779 static bool run_pidhigh(int dummy)
12780 {
12781         bool success = false;
12782         struct cli_state *cli = NULL;
12783         NTSTATUS status;
12784         struct tevent_context *ev = NULL;
12785         struct tevent_req *req = NULL;
12786         TALLOC_CTX *frame = talloc_stackframe();
12787
12788         printf("starting pid high test\n");
12789         if (!torture_open_connection(&cli, 0)) {
12790                 return false;
12791         }
12792         smbXcli_conn_set_sockopt(cli->conn, sockops);
12793
12794         ev = samba_tevent_context_init(frame);
12795         if (ev == NULL) {
12796                 goto fail;
12797         }
12798
12799         req = pid_echo_send(frame, ev, cli);
12800         if (req == NULL) {
12801                 goto fail;
12802         }
12803
12804         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12805                 goto fail;
12806         }
12807
12808         status = pid_echo_recv(req);
12809         if (NT_STATUS_IS_OK(status)) {
12810                 printf("pid high test ok\n");
12811                 success = true;
12812         }
12813
12814  fail:
12815
12816         TALLOC_FREE(frame);
12817         torture_close_connection(cli);
12818         return success;
12819 }
12820
12821 /*
12822   Test Windows open on a bad POSIX symlink.
12823  */
12824 static bool run_symlink_open_test(int dummy)
12825 {
12826         static struct cli_state *cli;
12827         const char *fname = "non_existant_file";
12828         const char *sname = "dangling_symlink";
12829         uint16_t fnum = (uint16_t)-1;
12830         bool correct = false;
12831         NTSTATUS status;
12832         TALLOC_CTX *frame = NULL;
12833
12834         frame = talloc_stackframe();
12835
12836         printf("Starting Windows bad symlink open test\n");
12837
12838         if (!torture_open_connection(&cli, 0)) {
12839                 TALLOC_FREE(frame);
12840                 return false;
12841         }
12842
12843         smbXcli_conn_set_sockopt(cli->conn, sockops);
12844
12845         status = torture_setup_unix_extensions(cli);
12846         if (!NT_STATUS_IS_OK(status)) {
12847                 TALLOC_FREE(frame);
12848                 return false;
12849         }
12850
12851         /* Ensure nothing exists. */
12852         cli_setatr(cli, fname, 0, 0);
12853         cli_posix_unlink(cli, fname);
12854         cli_setatr(cli, sname, 0, 0);
12855         cli_posix_unlink(cli, sname);
12856
12857         /* Create a symlink pointing nowhere. */
12858         status = cli_posix_symlink(cli, fname, sname);
12859         if (!NT_STATUS_IS_OK(status)) {
12860                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12861                         sname,
12862                         fname,
12863                         nt_errstr(status));
12864                 goto out;
12865         }
12866
12867         /* Now ensure that a Windows open doesn't hang. */
12868         status = cli_ntcreate(cli,
12869                         sname,
12870                         0,
12871                         FILE_READ_DATA|FILE_WRITE_DATA,
12872                         0,
12873                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12874                         FILE_OPEN_IF,
12875                         0x0,
12876                         0x0,
12877                         &fnum,
12878                         NULL);
12879
12880         /*
12881          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12882          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12883          * we use O_NOFOLLOW on the server or not.
12884          */
12885         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12886             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12887         {
12888                 correct = true;
12889         } else {
12890                 printf("cli_ntcreate of %s returned %s - should return"
12891                                 " either (%s) or (%s)\n",
12892                         sname,
12893                         nt_errstr(status),
12894                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12895                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12896                 goto out;
12897         }
12898
12899         correct = true;
12900
12901   out:
12902
12903         if (fnum != (uint16_t)-1) {
12904                 cli_close(cli, fnum);
12905                 fnum = (uint16_t)-1;
12906         }
12907
12908         cli_setatr(cli, sname, 0, 0);
12909         cli_posix_unlink(cli, sname);
12910         cli_setatr(cli, fname, 0, 0);
12911         cli_posix_unlink(cli, fname);
12912
12913         if (!torture_close_connection(cli)) {
12914                 correct = false;
12915         }
12916
12917         TALLOC_FREE(frame);
12918         return correct;
12919 }
12920
12921 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12922                                         const char *name,
12923                                         void *state)
12924 {
12925         char **mangled_name_return = (char **)state;
12926         bool is_mangled = strchr(finfo->name, '~');
12927
12928         if (is_mangled) {
12929                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12930                 if (*mangled_name_return == NULL) {
12931                         return NT_STATUS_NO_MEMORY;
12932                 }
12933         }
12934         return NT_STATUS_OK;
12935 }
12936
12937 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12938 {
12939         static struct cli_state *cli_posix = NULL;
12940         static struct cli_state *cli = NULL;
12941         uint16_t fnum = (uint16_t)-1;
12942         bool correct = false;
12943         const char *dname = "smb1_wild_mangle_unlink";
12944         const char *aname = "smb1_wild_mangle_unlink/a";
12945         const char *star_name = "smb1_wild_mangle_unlink/*";
12946         char *windows_unlink_name = NULL;
12947         char *mangled_name = NULL;
12948         NTSTATUS status;
12949
12950         printf("Starting SMB1 wild mangle unlink test\n");
12951
12952         /* Open a Windows connection. */
12953         if (!torture_open_connection(&cli, 0)) {
12954                 return false;
12955         }
12956
12957         smbXcli_conn_set_sockopt(cli->conn, sockops);
12958
12959         /* Open a POSIX connection. */
12960         if (!torture_open_connection(&cli_posix, 0)) {
12961                 goto out;
12962         }
12963
12964         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12965
12966         status = torture_setup_unix_extensions(cli_posix);
12967         if (!NT_STATUS_IS_OK(status)) {
12968                 printf("server doesn't support POSIX\n");
12969                 goto out;
12970         }
12971
12972         /* Start fresh. */
12973         torture_deltree(cli, dname);
12974
12975         /*
12976          * Create two files - 'a' and '*'.
12977          * We need POSIX extensions for this as '*'
12978          * is not a valid Windows name.
12979          */
12980
12981         status = cli_mkdir(cli, dname);
12982         if (!NT_STATUS_IS_OK(status)) {
12983                 printf("cli_mkdir of %s returned %s\n",
12984                         dname,
12985                         nt_errstr(status));
12986                 goto out;
12987         }
12988
12989         status = cli_posix_open(cli_posix,
12990                                 aname,
12991                                 O_RDWR|O_CREAT|O_EXCL,
12992                                 0660,
12993                                 &fnum);
12994         if (!NT_STATUS_IS_OK(status)) {
12995                 printf("cli_posix_open (create) of %s returned %s\n",
12996                         aname,
12997                         nt_errstr(status));
12998                 goto out;
12999         }
13000         status = cli_close(cli_posix, fnum);
13001         if (!NT_STATUS_IS_OK(status)) {
13002                 goto out;
13003         }
13004         status = cli_posix_open(cli_posix,
13005                                 star_name,
13006                                 O_RDWR|O_CREAT|O_EXCL,
13007                                 0660,
13008                                 &fnum);
13009         if (!NT_STATUS_IS_OK(status)) {
13010                 printf("cli_posix_open (create) of %s returned %s\n",
13011                         star_name,
13012                         nt_errstr(status));
13013                 goto out;
13014         }
13015         status = cli_close(cli_posix, fnum);
13016         if (!NT_STATUS_IS_OK(status)) {
13017                 goto out;
13018         }
13019
13020         status = cli_list(cli,
13021                         star_name,
13022                         0,
13023                         smb1_wild_mangle_list_fn,
13024                         &mangled_name);
13025         if (!NT_STATUS_IS_OK(status)) {
13026                 printf("cli_list of %s returned %s\n",
13027                         star_name,
13028                         nt_errstr(status));
13029                 goto out;
13030         }
13031
13032         if (mangled_name == NULL) {
13033                 goto out;
13034         }
13035
13036         printf("mangled_name = %s\n",
13037                 mangled_name);
13038
13039         /*
13040          * Try a Windows unlink with the mangled name.
13041          * This should *NOT* unlink the 'a' name.
13042          */
13043
13044         windows_unlink_name = talloc_asprintf(cli_posix,
13045                                         "%s\\%s",
13046                                         dname,
13047                                         mangled_name);
13048
13049         status = cli_unlink(cli, windows_unlink_name, 0);
13050         if (!NT_STATUS_IS_OK(status)) {
13051                 printf("cli_unlink of %s returned %s\n",
13052                         windows_unlink_name,
13053                         nt_errstr(status));
13054                 goto out;
13055         }
13056
13057         /* Does 'a' still exist ? */
13058         status = cli_posix_open(cli_posix,
13059                                 aname,
13060                                 O_RDONLY,
13061                                 0,
13062                                 &fnum);
13063         if (!NT_STATUS_IS_OK(status)) {
13064                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13065                         aname,
13066                         nt_errstr(status));
13067                 goto out;
13068         }
13069
13070         status = cli_close(cli_posix, fnum);
13071         if (!NT_STATUS_IS_OK(status)) {
13072                 goto out;
13073         }
13074
13075         correct = true;
13076
13077   out:
13078
13079         TALLOC_FREE(windows_unlink_name);
13080         TALLOC_FREE(mangled_name);
13081
13082         if (cli != NULL) {
13083                 torture_deltree(cli, dname);
13084                 torture_close_connection(cli);
13085         }
13086
13087         if (cli_posix != NULL) {
13088                 torture_close_connection(cli_posix);
13089         }
13090
13091         return correct;
13092 }
13093
13094 static bool run_smb1_wild_mangle_rename_test(int dummy)
13095 {
13096         static struct cli_state *cli_posix = NULL;
13097         static struct cli_state *cli = NULL;
13098         uint16_t fnum = (uint16_t)-1;
13099         bool correct = false;
13100         const char *dname = "smb1_wild_mangle_rename";
13101         const char *fooname = "smb1_wild_mangle_rename/foo";
13102         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13103         const char *wild_name = "smb1_wild_mangle_rename/*";
13104         char *windows_rename_src = NULL;
13105         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13106         char *mangled_name = NULL;
13107         NTSTATUS status;
13108
13109         printf("Starting SMB1 wild mangle rename test\n");
13110
13111         if (!torture_open_connection(&cli_posix, 0)) {
13112                 return false;
13113         }
13114
13115         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13116
13117         status = torture_setup_unix_extensions(cli_posix);
13118         if (!NT_STATUS_IS_OK(status)) {
13119                 printf("server doesn't support POSIX\n");
13120                 return false;
13121         }
13122
13123         /* Open a Windows connection. */
13124         if (!torture_open_connection(&cli, 0)) {
13125                 goto out;
13126         }
13127
13128         smbXcli_conn_set_sockopt(cli->conn, sockops);
13129
13130         /* Ensure we start from fresh. */
13131         torture_deltree(cli, dname);
13132
13133         /*
13134          * Create two files - 'foo' and 'fo*'.
13135          * We need POSIX extensions for this as 'fo*'
13136          * is not a valid Windows name.
13137          */
13138
13139         status = cli_posix_mkdir(cli_posix, dname, 0770);
13140         if (!NT_STATUS_IS_OK(status)) {
13141                 printf("cli_posix_mkdir of %s returned %s\n",
13142                         dname,
13143                         nt_errstr(status));
13144                 goto out;
13145         }
13146
13147         status = cli_posix_open(cli_posix,
13148                                 fooname,
13149                                 O_RDWR|O_CREAT|O_EXCL,
13150                                 0660,
13151                                 &fnum);
13152         if (!NT_STATUS_IS_OK(status)) {
13153                 printf("cli_posix_open (create) of %s returned %s\n",
13154                         fooname,
13155                         nt_errstr(status));
13156                 goto out;
13157         }
13158         status = cli_close(cli_posix, fnum);
13159         if (!NT_STATUS_IS_OK(status)) {
13160                 goto out;
13161         }
13162         status = cli_posix_open(cli_posix,
13163                                 foostar_name,
13164                                 O_RDWR|O_CREAT|O_EXCL,
13165                                 0660,
13166                                 &fnum);
13167         if (!NT_STATUS_IS_OK(status)) {
13168                 printf("cli_posix_open (create) of %s returned %s\n",
13169                         foostar_name,
13170                         nt_errstr(status));
13171                 goto out;
13172         }
13173         status = cli_close(cli_posix, fnum);
13174         if (!NT_STATUS_IS_OK(status)) {
13175                 goto out;
13176         }
13177
13178         /*
13179          * Get the mangled name. We can re-use the
13180          * previous smb1_wild_mangle_list_fn for this.
13181          */
13182
13183         status = cli_list(cli,
13184                         wild_name,
13185                         0,
13186                         smb1_wild_mangle_list_fn,
13187                         &mangled_name);
13188         if (!NT_STATUS_IS_OK(status)) {
13189                 printf("cli_list of %s returned %s\n",
13190                         wild_name,
13191                         nt_errstr(status));
13192                 goto out;
13193         }
13194
13195         if (mangled_name == NULL) {
13196                 goto out;
13197         }
13198
13199         printf("mangled_name = %s\n",
13200                 mangled_name);
13201
13202         /*
13203          * Try a Windows rename with the mangled name.
13204          * This should *NOT* rename the 'foo' name.
13205          */
13206
13207         windows_rename_src = talloc_asprintf(cli_posix,
13208                                         "%s\\%s",
13209                                         dname,
13210                                         mangled_name);
13211
13212         status = cli_rename(cli,
13213                         windows_rename_src,
13214                         windows_rename_dst,
13215                         false);
13216         if (!NT_STATUS_IS_OK(status)) {
13217                 printf("cli_rename of %s -> %s returned %s\n",
13218                         windows_rename_src,
13219                         windows_rename_dst,
13220                         nt_errstr(status));
13221                 goto out;
13222         }
13223
13224         /* Does 'foo' still exist ? */
13225         status = cli_posix_open(cli_posix,
13226                                 fooname,
13227                                 O_RDONLY,
13228                                 0,
13229                                 &fnum);
13230         if (!NT_STATUS_IS_OK(status)) {
13231                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13232                         fooname,
13233                         nt_errstr(status));
13234                 goto out;
13235         }
13236
13237         status = cli_close(cli_posix, fnum);
13238         if (!NT_STATUS_IS_OK(status)) {
13239                 goto out;
13240         }
13241
13242         correct = true;
13243
13244   out:
13245
13246         TALLOC_FREE(mangled_name);
13247         TALLOC_FREE(windows_rename_src);
13248
13249         if (cli != NULL) {
13250                 torture_deltree(cli, dname);
13251                 torture_close_connection(cli);
13252         }
13253
13254         torture_close_connection(cli_posix);
13255
13256         return correct;
13257 }
13258
13259 /*
13260  * Only testing minimal time strings, as the others
13261  * need (locale-dependent) guessing at what strftime does and
13262  * even may differ in builds.
13263  */
13264 static bool timesubst_test(void)
13265 {
13266         TALLOC_CTX *ctx = NULL;
13267         /* Sa 23. Dez 04:33:20 CET 2017 */
13268         const struct timeval tv = { 1514000000, 123 };
13269         const char* expect_minimal = "20171223_033320";
13270         const char* expect_minus   = "20171223_033320_000123";
13271         char *s;
13272         char *env_tz, *orig_tz = NULL;
13273         bool result = true;
13274
13275         ctx = talloc_new(NULL);
13276
13277         env_tz = getenv("TZ");
13278         if(env_tz) {
13279                 orig_tz = talloc_strdup(ctx, env_tz);
13280         }
13281         setenv("TZ", "UTC", 1);
13282
13283         s = minimal_timeval_string(ctx, &tv, false);
13284
13285         if(!s || strcmp(s, expect_minimal)) {
13286                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13287                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13288                 result = false;
13289         }
13290         TALLOC_FREE(s);
13291         s = minimal_timeval_string(ctx, &tv, true);
13292         if(!s || strcmp(s, expect_minus)) {
13293                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13294                        "[%s]\n", s ? s : "<nil>", expect_minus);
13295                 result = false;
13296         }
13297         TALLOC_FREE(s);
13298
13299         if(orig_tz) {
13300                 setenv("TZ", orig_tz, 1);
13301         }
13302
13303         TALLOC_FREE(ctx);
13304         return result;
13305 }
13306
13307 static bool run_local_substitute(int dummy)
13308 {
13309         bool ok = true;
13310
13311         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13312         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13313         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13314         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13315         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13316         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13317         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13318         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13319         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13320         /* Substitution depends on current time, so better test the underlying
13321            formatting function. At least covers %t. */
13322         ok &= timesubst_test();
13323
13324         /* Different captialization rules in sub_basic... */
13325
13326         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13327                        "blaDOM") == 0);
13328
13329         return ok;
13330 }
13331
13332 static bool run_local_base64(int dummy)
13333 {
13334         int i;
13335         bool ret = true;
13336
13337         for (i=1; i<2000; i++) {
13338                 DATA_BLOB blob1, blob2;
13339                 char *b64;
13340
13341                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13342                 blob1.length = i;
13343                 generate_random_buffer(blob1.data, blob1.length);
13344
13345                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13346                 if (b64 == NULL) {
13347                         d_fprintf(stderr, "base64_encode_data_blob failed "
13348                                   "for %d bytes\n", i);
13349                         ret = false;
13350                 }
13351                 blob2 = base64_decode_data_blob(b64);
13352                 TALLOC_FREE(b64);
13353
13354                 if (data_blob_cmp(&blob1, &blob2)) {
13355                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13356                                   "bytes\n", i);
13357                         ret = false;
13358                 }
13359                 TALLOC_FREE(blob1.data);
13360                 data_blob_free(&blob2);
13361         }
13362         return ret;
13363 }
13364
13365 static void parse_fn(const struct gencache_timeout *t,
13366                      DATA_BLOB blob,
13367                      void *private_data)
13368 {
13369         return;
13370 }
13371
13372 static bool run_local_gencache(int dummy)
13373 {
13374         char *val;
13375         time_t tm;
13376         DATA_BLOB blob;
13377         char v;
13378         struct memcache *mem;
13379         int i;
13380
13381         mem = memcache_init(NULL, 0);
13382         if (mem == NULL) {
13383                 d_printf("%s: memcache_init failed\n", __location__);
13384                 return false;
13385         }
13386         memcache_set_global(mem);
13387
13388         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13389                 d_printf("%s: gencache_set() failed\n", __location__);
13390                 return False;
13391         }
13392
13393         if (!gencache_get("foo", NULL, NULL, NULL)) {
13394                 d_printf("%s: gencache_get() failed\n", __location__);
13395                 return False;
13396         }
13397
13398         for (i=0; i<1000000; i++) {
13399                 gencache_parse("foo", parse_fn, NULL);
13400         }
13401
13402         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13403                 d_printf("%s: gencache_get() failed\n", __location__);
13404                 return False;
13405         }
13406         TALLOC_FREE(val);
13407
13408         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13409                 d_printf("%s: gencache_get() failed\n", __location__);
13410                 return False;
13411         }
13412
13413         if (strcmp(val, "bar") != 0) {
13414                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13415                          __location__, val, "bar");
13416                 TALLOC_FREE(val);
13417                 return False;
13418         }
13419
13420         TALLOC_FREE(val);
13421
13422         if (!gencache_del("foo")) {
13423                 d_printf("%s: gencache_del() failed\n", __location__);
13424                 return False;
13425         }
13426         if (gencache_del("foo")) {
13427                 d_printf("%s: second gencache_del() succeeded\n",
13428                          __location__);
13429                 return False;
13430         }
13431
13432         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13433                 d_printf("%s: gencache_get() on deleted entry "
13434                          "succeeded\n", __location__);
13435                 return False;
13436         }
13437
13438         blob = data_blob_string_const_null("bar");
13439         tm = time(NULL) + 60;
13440
13441         if (!gencache_set_data_blob("foo", blob, tm)) {
13442                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13443                 return False;
13444         }
13445
13446         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13447                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13448                 return False;
13449         }
13450
13451         if (strcmp((const char *)blob.data, "bar") != 0) {
13452                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13453                          __location__, (const char *)blob.data, "bar");
13454                 data_blob_free(&blob);
13455                 return False;
13456         }
13457
13458         data_blob_free(&blob);
13459
13460         if (!gencache_del("foo")) {
13461                 d_printf("%s: gencache_del() failed\n", __location__);
13462                 return False;
13463         }
13464         if (gencache_del("foo")) {
13465                 d_printf("%s: second gencache_del() succeeded\n",
13466                          __location__);
13467                 return False;
13468         }
13469
13470         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13471                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13472                          "succeeded\n", __location__);
13473                 return False;
13474         }
13475
13476         v = 1;
13477         blob.data = (uint8_t *)&v;
13478         blob.length = sizeof(v);
13479
13480         if (!gencache_set_data_blob("blob", blob, tm)) {
13481                 d_printf("%s: gencache_set_data_blob() failed\n",
13482                          __location__);
13483                 return false;
13484         }
13485         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13486                 d_printf("%s: gencache_get succeeded\n", __location__);
13487                 return false;
13488         }
13489
13490         return True;
13491 }
13492
13493 static bool rbt_testflags(struct db_context *db, const char *key,
13494                           const char *value)
13495 {
13496         bool ret = false;
13497         NTSTATUS status;
13498         struct db_record *rec;
13499
13500         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13501         if (rec == NULL) {
13502                 d_fprintf(stderr, "fetch_locked failed\n");
13503                 goto done;
13504         }
13505
13506         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13507         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13508                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13509                           nt_errstr(status));
13510                 goto done;
13511         }
13512
13513         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13514                                      TDB_INSERT);
13515         if (!NT_STATUS_IS_OK(status)) {
13516                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13517                           nt_errstr(status));
13518                 goto done;
13519         }
13520
13521         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13522         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13523                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13524                           nt_errstr(status));
13525                 goto done;
13526         }
13527
13528         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13529         if (!NT_STATUS_IS_OK(status)) {
13530                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13531                           nt_errstr(status));
13532                 goto done;
13533         }
13534
13535         ret = true;
13536 done:
13537         TALLOC_FREE(rec);
13538         return ret;
13539 }
13540
13541 static bool rbt_testval(struct db_context *db, const char *key,
13542                         const char *value)
13543 {
13544         struct db_record *rec;
13545         TDB_DATA data = string_tdb_data(value);
13546         bool ret = false;
13547         NTSTATUS status;
13548         TDB_DATA dbvalue;
13549
13550         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13551         if (rec == NULL) {
13552                 d_fprintf(stderr, "fetch_locked failed\n");
13553                 goto done;
13554         }
13555         status = dbwrap_record_store(rec, data, 0);
13556         if (!NT_STATUS_IS_OK(status)) {
13557                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13558                 goto done;
13559         }
13560         TALLOC_FREE(rec);
13561
13562         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13563         if (rec == NULL) {
13564                 d_fprintf(stderr, "second fetch_locked failed\n");
13565                 goto done;
13566         }
13567
13568         dbvalue = dbwrap_record_get_value(rec);
13569         if ((dbvalue.dsize != data.dsize)
13570             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13571                 d_fprintf(stderr, "Got wrong data back\n");
13572                 goto done;
13573         }
13574
13575         ret = true;
13576  done:
13577         TALLOC_FREE(rec);
13578         return ret;
13579 }
13580
13581 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13582 {
13583         int *count2 = (int *)private_data;
13584         (*count2)++;
13585         return 0;
13586 }
13587
13588 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13589 {
13590         int *count2 = (int *)private_data;
13591         (*count2)++;
13592         dbwrap_record_delete(rec);
13593         return 0;
13594 }
13595
13596 static bool run_local_rbtree(int dummy)
13597 {
13598         struct db_context *db;
13599         bool ret = false;
13600         int i;
13601         NTSTATUS status;
13602         int count = 0;
13603         int count2 = 0;
13604
13605         db = db_open_rbt(NULL);
13606
13607         if (db == NULL) {
13608                 d_fprintf(stderr, "db_open_rbt failed\n");
13609                 return false;
13610         }
13611
13612         if (!rbt_testflags(db, "firstkey", "firstval")) {
13613                 goto done;
13614         }
13615
13616         for (i = 0; i < 999; i++) {
13617                 char key[sizeof("key-9223372036854775807")];
13618                 char value[sizeof("value-9223372036854775807")];
13619
13620                 snprintf(key, sizeof(key), "key%ld", random());
13621                 snprintf(value, sizeof(value) ,"value%ld", random());
13622
13623                 if (!rbt_testval(db, key, value)) {
13624                         goto done;
13625                 }
13626
13627                 snprintf(value, sizeof(value) ,"value%ld", random());
13628
13629                 if (!rbt_testval(db, key, value)) {
13630                         goto done;
13631                 }
13632         }
13633
13634         ret = true;
13635         count = 0; count2 = 0;
13636         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13637                                       &count2, &count);
13638         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13639         if ((count != count2) || (count != 1000)) {
13640                 ret = false;
13641         }
13642         count = 0; count2 = 0;
13643         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13644                                  &count2, &count);
13645         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13646         if ((count != count2) || (count != 1000)) {
13647                 ret = false;
13648         }
13649         count = 0; count2 = 0;
13650         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13651                                       &count2, &count);
13652         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13653         if ((count != count2) || (count != 0)) {
13654                 ret = false;
13655         }
13656
13657  done:
13658         TALLOC_FREE(db);
13659         return ret;
13660 }
13661
13662
13663 /*
13664   local test for character set functions
13665
13666   This is a very simple test for the functionality in convert_string_error()
13667  */
13668 static bool run_local_convert_string(int dummy)
13669 {
13670         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13671         const char *test_strings[2] = { "March", "M\303\244rz" };
13672         char dst[7];
13673         int i;
13674
13675         for (i=0; i<2; i++) {
13676                 const char *str = test_strings[i];
13677                 int len = strlen(str);
13678                 size_t converted_size;
13679                 bool ret;
13680
13681                 memset(dst, 'X', sizeof(dst));
13682
13683                 /* first try with real source length */
13684                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13685                                            str, len,
13686                                            dst, sizeof(dst),
13687                                            &converted_size);
13688                 if (ret != true) {
13689                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13690                         goto failed;
13691                 }
13692
13693                 if (converted_size != len) {
13694                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13695                                   str, len, (int)converted_size);
13696                         goto failed;
13697                 }
13698
13699                 if (strncmp(str, dst, converted_size) != 0) {
13700                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13701                         goto failed;
13702                 }
13703
13704                 if (strlen(str) != converted_size) {
13705                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13706                                   (int)strlen(str), (int)converted_size);
13707                         goto failed;
13708                 }
13709
13710                 if (dst[converted_size] != 'X') {
13711                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13712                         goto failed;
13713                 }
13714
13715                 /* now with srclen==-1, this causes the nul to be
13716                  * converted too */
13717                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13718                                            str, -1,
13719                                            dst, sizeof(dst),
13720                                            &converted_size);
13721                 if (ret != true) {
13722                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13723                         goto failed;
13724                 }
13725
13726                 if (converted_size != len+1) {
13727                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13728                                   str, len, (int)converted_size);
13729                         goto failed;
13730                 }
13731
13732                 if (strncmp(str, dst, converted_size) != 0) {
13733                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13734                         goto failed;
13735                 }
13736
13737                 if (len+1 != converted_size) {
13738                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13739                                   len+1, (int)converted_size);
13740                         goto failed;
13741                 }
13742
13743                 if (dst[converted_size] != 'X') {
13744                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13745                         goto failed;
13746                 }
13747
13748         }
13749
13750
13751         TALLOC_FREE(tmp_ctx);
13752         return true;
13753 failed:
13754         TALLOC_FREE(tmp_ctx);
13755         return false;
13756 }
13757
13758 static bool run_local_string_to_sid(int dummy) {
13759         struct dom_sid sid;
13760
13761         if (string_to_sid(&sid, "S--1-5-32-545")) {
13762                 printf("allowing S--1-5-32-545\n");
13763                 return false;
13764         }
13765         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13766                 printf("allowing S-1-5-32-+545\n");
13767                 return false;
13768         }
13769         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")) {
13770                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13771                 return false;
13772         }
13773         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13774                 printf("allowing S-1-5-32-545-abc\n");
13775                 return false;
13776         }
13777         if (string_to_sid(&sid, "S-300-5-32-545")) {
13778                 printf("allowing S-300-5-32-545\n");
13779                 return false;
13780         }
13781         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13782                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13783                 return false;
13784         }
13785         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13786                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13787                 return false;
13788         }
13789         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13790                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13791                 return false;
13792         }
13793         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13794                 printf("could not parse S-1-5-32-545\n");
13795                 return false;
13796         }
13797         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13798                 struct dom_sid_buf buf;
13799                 printf("mis-parsed S-1-5-32-545 as %s\n",
13800                        dom_sid_str_buf(&sid, &buf));
13801                 return false;
13802         }
13803         return true;
13804 }
13805
13806 static bool sid_to_string_test(const char *expected) {
13807         char *str;
13808         bool res = true;
13809         struct dom_sid sid;
13810
13811         if (!string_to_sid(&sid, expected)) {
13812                 printf("could not parse %s\n", expected);
13813                 return false;
13814         }
13815
13816         str = dom_sid_string(NULL, &sid);
13817         if (strcmp(str, expected)) {
13818                 printf("Comparison failed (%s != %s)\n", str, expected);
13819                 res = false;
13820         }
13821         TALLOC_FREE(str);
13822         return res;
13823 }
13824
13825 static bool run_local_sid_to_string(int dummy) {
13826         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13827                 return false;
13828         if (!sid_to_string_test("S-1-545"))
13829                 return false;
13830         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13831                 return false;
13832         return true;
13833 }
13834
13835 static bool run_local_binary_to_sid(int dummy) {
13836         ssize_t ret;
13837         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13838         static const uint8_t good_binary_sid[] = {
13839                 0x1, /* revision number */
13840                 15, /* num auths */
13841                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13842                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13843                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13844                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13845                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13846                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13847                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13848                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13849                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13850                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13851                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13852                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13853                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13854                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13855                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13856                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13857         };
13858
13859         static const uint8_t long_binary_sid[] = {
13860                 0x1, /* revision number */
13861                 15, /* num auths */
13862                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13863                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13864                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13865                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13866                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13867                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13868                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13869                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13870                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13871                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13872                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13873                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13874                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13875                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13876                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13877                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13878                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13879                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13880                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13881         };
13882
13883         static const uint8_t long_binary_sid2[] = {
13884                 0x1, /* revision number */
13885                 32, /* num auths */
13886                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13887                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13888                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13889                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13890                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13891                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13892                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13893                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13894                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13895                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13896                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13897                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13898                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13899                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13900                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13901                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13902                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13903                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13904                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13905                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13906                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13907                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13908                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13909                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13910                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13911                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13912                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13913                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13914                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13915                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13916                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13917                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13918                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13919         };
13920
13921         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13922         if (ret == -1) {
13923                 return false;
13924         }
13925         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13926         if (ret != -1) {
13927                 return false;
13928         }
13929         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13930         if (ret != -1) {
13931                 return false;
13932         }
13933         return true;
13934 }
13935
13936 /* Split a path name into filename and stream name components. Canonicalise
13937  * such that an implicit $DATA token is always explicit.
13938  *
13939  * The "specification" of this function can be found in the
13940  * run_local_stream_name() function in torture.c, I've tried those
13941  * combinations against a W2k3 server.
13942  */
13943
13944 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13945                                        char **pbase, char **pstream)
13946 {
13947         char *base = NULL;
13948         char *stream = NULL;
13949         char *sname; /* stream name */
13950         const char *stype; /* stream type */
13951
13952         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13953
13954         sname = strchr_m(fname, ':');
13955
13956         if (sname == NULL) {
13957                 if (pbase != NULL) {
13958                         base = talloc_strdup(mem_ctx, fname);
13959                         NT_STATUS_HAVE_NO_MEMORY(base);
13960                 }
13961                 goto done;
13962         }
13963
13964         if (pbase != NULL) {
13965                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13966                 NT_STATUS_HAVE_NO_MEMORY(base);
13967         }
13968
13969         sname += 1;
13970
13971         stype = strchr_m(sname, ':');
13972
13973         if (stype == NULL) {
13974                 sname = talloc_strdup(mem_ctx, sname);
13975                 stype = "$DATA";
13976         }
13977         else {
13978                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13979                         /*
13980                          * If there is an explicit stream type, so far we only
13981                          * allow $DATA. Is there anything else allowed? -- vl
13982                          */
13983                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13984                         TALLOC_FREE(base);
13985                         return NT_STATUS_OBJECT_NAME_INVALID;
13986                 }
13987                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13988                 stype += 1;
13989         }
13990
13991         if (sname == NULL) {
13992                 TALLOC_FREE(base);
13993                 return NT_STATUS_NO_MEMORY;
13994         }
13995
13996         if (sname[0] == '\0') {
13997                 /*
13998                  * no stream name, so no stream
13999                  */
14000                 goto done;
14001         }
14002
14003         if (pstream != NULL) {
14004                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14005                 if (stream == NULL) {
14006                         TALLOC_FREE(sname);
14007                         TALLOC_FREE(base);
14008                         return NT_STATUS_NO_MEMORY;
14009                 }
14010                 /*
14011                  * upper-case the type field
14012                  */
14013                 (void)strupper_m(strchr_m(stream, ':')+1);
14014         }
14015
14016  done:
14017         if (pbase != NULL) {
14018                 *pbase = base;
14019         }
14020         if (pstream != NULL) {
14021                 *pstream = stream;
14022         }
14023         return NT_STATUS_OK;
14024 }
14025
14026 static bool test_stream_name(const char *fname, const char *expected_base,
14027                              const char *expected_stream,
14028                              NTSTATUS expected_status)
14029 {
14030         NTSTATUS status;
14031         char *base = NULL;
14032         char *stream = NULL;
14033
14034         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14035         if (!NT_STATUS_EQUAL(status, expected_status)) {
14036                 goto error;
14037         }
14038
14039         if (!NT_STATUS_IS_OK(status)) {
14040                 return true;
14041         }
14042
14043         if (base == NULL) goto error;
14044
14045         if (strcmp(expected_base, base) != 0) goto error;
14046
14047         if ((expected_stream != NULL) && (stream == NULL)) goto error;
14048         if ((expected_stream == NULL) && (stream != NULL)) goto error;
14049
14050         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14051                 goto error;
14052
14053         TALLOC_FREE(base);
14054         TALLOC_FREE(stream);
14055         return true;
14056
14057  error:
14058         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14059                   fname, expected_base ? expected_base : "<NULL>",
14060                   expected_stream ? expected_stream : "<NULL>",
14061                   nt_errstr(expected_status));
14062         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14063                   base ? base : "<NULL>", stream ? stream : "<NULL>",
14064                   nt_errstr(status));
14065         TALLOC_FREE(base);
14066         TALLOC_FREE(stream);
14067         return false;
14068 }
14069
14070 static bool run_local_stream_name(int dummy)
14071 {
14072         bool ret = true;
14073
14074         ret &= test_stream_name(
14075                 "bla", "bla", NULL, NT_STATUS_OK);
14076         ret &= test_stream_name(
14077                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14078         ret &= test_stream_name(
14079                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14080         ret &= test_stream_name(
14081                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14082         ret &= test_stream_name(
14083                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14084         ret &= test_stream_name(
14085                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14086         ret &= test_stream_name(
14087                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14088         ret &= test_stream_name(
14089                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14090
14091         return ret;
14092 }
14093
14094 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14095 {
14096         if (a.length != b.length) {
14097                 printf("a.length=%d != b.length=%d\n",
14098                        (int)a.length, (int)b.length);
14099                 return false;
14100         }
14101         if (memcmp(a.data, b.data, a.length) != 0) {
14102                 printf("a.data and b.data differ\n");
14103                 return false;
14104         }
14105         return true;
14106 }
14107
14108 static bool run_local_memcache(int dummy)
14109 {
14110         struct memcache *cache;
14111         DATA_BLOB k1, k2, k3, k4, k5;
14112         DATA_BLOB d1, d3;
14113         DATA_BLOB v1, v3;
14114
14115         TALLOC_CTX *mem_ctx;
14116         char *ptr1 = NULL;
14117         char *ptr2 = NULL;
14118         char *ptr3 = NULL;
14119
14120         char *str1, *str2;
14121         size_t size1, size2;
14122         bool ret = false;
14123
14124         mem_ctx = talloc_init("foo");
14125         if (mem_ctx == NULL) {
14126                 return false;
14127         }
14128
14129         /* STAT_CACHE TESTS */
14130
14131         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14132
14133         if (cache == NULL) {
14134                 printf("memcache_init failed\n");
14135                 return false;
14136         }
14137
14138         d1 = data_blob_const("d1", 2);
14139         d3 = data_blob_const("d3", 2);
14140
14141         k1 = data_blob_const("d1", 2);
14142         k2 = data_blob_const("d2", 2);
14143         k3 = data_blob_const("d3", 2);
14144         k4 = data_blob_const("d4", 2);
14145         k5 = data_blob_const("d5", 2);
14146
14147         memcache_add(cache, STAT_CACHE, k1, d1);
14148
14149         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14150                 printf("could not find k1\n");
14151                 return false;
14152         }
14153         if (!data_blob_equal(d1, v1)) {
14154                 return false;
14155         }
14156
14157         memcache_add(cache, STAT_CACHE, k1, d3);
14158
14159         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14160                 printf("could not find replaced k1\n");
14161                 return false;
14162         }
14163         if (!data_blob_equal(d3, v3)) {
14164                 return false;
14165         }
14166
14167         TALLOC_FREE(cache);
14168
14169         /* GETWD_CACHE TESTS */
14170         str1 = talloc_strdup(mem_ctx, "string1");
14171         if (str1 == NULL) {
14172                 return false;
14173         }
14174         ptr2 = str1; /* Keep an alias for comparison. */
14175
14176         str2 = talloc_strdup(mem_ctx, "string2");
14177         if (str2 == NULL) {
14178                 return false;
14179         }
14180
14181         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14182         if (cache == NULL) {
14183                 printf("memcache_init failed\n");
14184                 return false;
14185         }
14186
14187         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14188         /* str1 == NULL now. */
14189         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14190         if (ptr1 == NULL) {
14191                 printf("could not find k2\n");
14192                 return false;
14193         }
14194         if (ptr1 != ptr2) {
14195                 printf("fetch of k2 got wrong string\n");
14196                 return false;
14197         }
14198
14199         /* Add a blob to ensure k2 gets purged. */
14200         d3 = data_blob_talloc_zero(mem_ctx, 180);
14201         memcache_add(cache, STAT_CACHE, k3, d3);
14202
14203         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14204         if (ptr2 != NULL) {
14205                 printf("Did find k2, should have been purged\n");
14206                 return false;
14207         }
14208
14209         /*
14210          * Test that talloc size also is accounted in memcache and
14211          * causes purge of other object.
14212          */
14213
14214         str1 = talloc_zero_size(mem_ctx, 100);
14215         str2 = talloc_zero_size(mem_ctx, 100);
14216
14217         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14218         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14219
14220         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14221         if (ptr3 != NULL) {
14222                 printf("Did find k4, should have been purged\n");
14223                 return false;
14224         }
14225
14226         /*
14227          * Test that adding a duplicate non-talloced
14228          * key/value on top of a talloced key/value takes account
14229          * of the talloc_freed value size.
14230          */
14231         TALLOC_FREE(cache);
14232         TALLOC_FREE(mem_ctx);
14233
14234         mem_ctx = talloc_init("key_replace");
14235         if (mem_ctx == NULL) {
14236                 return false;
14237         }
14238
14239         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14240         if (cache == NULL) {
14241                 return false;
14242         }
14243
14244         /*
14245          * Add a 100 byte talloced string. This will
14246          * store a (4 or 8 byte) pointer and record the
14247          * total talloced size.
14248          */
14249         str1 = talloc_zero_size(mem_ctx, 100);
14250         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14251         /*
14252          * Now overwrite with a small talloced
14253          * value. This should fit in the existing size
14254          * and the total talloced size should be removed
14255          * from the cache size.
14256          */
14257         str1 = talloc_zero_size(mem_ctx, 2);
14258         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14259         /*
14260          * Now store a 20 byte string. If the
14261          * total talloced size wasn't accounted for
14262          * and removed in the overwrite, then this
14263          * will evict k4.
14264          */
14265         str2 = talloc_zero_size(mem_ctx, 20);
14266         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14267
14268         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14269         if (ptr3 == NULL) {
14270                 printf("Did not find k4, should not have been purged\n");
14271                 return false;
14272         }
14273
14274         TALLOC_FREE(cache);
14275         TALLOC_FREE(mem_ctx);
14276
14277         mem_ctx = talloc_init("foo");
14278         if (mem_ctx == NULL) {
14279                 return false;
14280         }
14281
14282         cache = memcache_init(NULL, 0);
14283         if (cache == NULL) {
14284                 return false;
14285         }
14286
14287         str1 = talloc_strdup(mem_ctx, "string1");
14288         if (str1 == NULL) {
14289                 return false;
14290         }
14291         str2 = talloc_strdup(mem_ctx, "string2");
14292         if (str2 == NULL) {
14293                 return false;
14294         }
14295         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14296                             data_blob_string_const("torture"), &str1);
14297         size1 = talloc_total_size(cache);
14298
14299         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14300                             data_blob_string_const("torture"), &str2);
14301         size2 = talloc_total_size(cache);
14302
14303         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14304
14305         if (size2 > size1) {
14306                 printf("memcache leaks memory!\n");
14307                 goto fail;
14308         }
14309
14310         ret = true;
14311  fail:
14312         TALLOC_FREE(cache);
14313         return ret;
14314 }
14315
14316 static void wbclient_done(struct tevent_req *req)
14317 {
14318         wbcErr wbc_err;
14319         struct winbindd_response *wb_resp;
14320         int *i = (int *)tevent_req_callback_data_void(req);
14321
14322         wbc_err = wb_trans_recv(req, req, &wb_resp);
14323         TALLOC_FREE(req);
14324         *i += 1;
14325         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14326 }
14327
14328 static bool run_wbclient_multi_ping(int dummy)
14329 {
14330         struct tevent_context *ev;
14331         struct wb_context **wb_ctx;
14332         struct winbindd_request wb_req;
14333         bool result = false;
14334         int i, j;
14335
14336         BlockSignals(True, SIGPIPE);
14337
14338         ev = tevent_context_init(talloc_tos());
14339         if (ev == NULL) {
14340                 goto fail;
14341         }
14342
14343         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14344         if (wb_ctx == NULL) {
14345                 goto fail;
14346         }
14347
14348         ZERO_STRUCT(wb_req);
14349         wb_req.cmd = WINBINDD_PING;
14350
14351         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14352
14353         for (i=0; i<torture_nprocs; i++) {
14354                 wb_ctx[i] = wb_context_init(ev, NULL);
14355                 if (wb_ctx[i] == NULL) {
14356                         goto fail;
14357                 }
14358                 for (j=0; j<torture_numops; j++) {
14359                         struct tevent_req *req;
14360                         req = wb_trans_send(ev, ev, wb_ctx[i],
14361                                             (j % 2) == 0, &wb_req);
14362                         if (req == NULL) {
14363                                 goto fail;
14364                         }
14365                         tevent_req_set_callback(req, wbclient_done, &i);
14366                 }
14367         }
14368
14369         i = 0;
14370
14371         while (i < torture_nprocs * torture_numops) {
14372                 tevent_loop_once(ev);
14373         }
14374
14375         result = true;
14376  fail:
14377         TALLOC_FREE(ev);
14378         return result;
14379 }
14380
14381 static bool dbtrans_inc(struct db_context *db)
14382 {
14383         struct db_record *rec;
14384         uint32_t val;
14385         bool ret = false;
14386         NTSTATUS status;
14387         TDB_DATA value;
14388
14389         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14390         if (rec == NULL) {
14391                 printf(__location__ "fetch_lock failed\n");
14392                 return false;
14393         }
14394
14395         value = dbwrap_record_get_value(rec);
14396
14397         if (value.dsize != sizeof(uint32_t)) {
14398                 printf(__location__ "value.dsize = %d\n",
14399                        (int)value.dsize);
14400                 goto fail;
14401         }
14402
14403         memcpy(&val, value.dptr, sizeof(val));
14404         val += 1;
14405
14406         status = dbwrap_record_store(
14407                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14408         if (!NT_STATUS_IS_OK(status)) {
14409                 printf(__location__ "store failed: %s\n",
14410                        nt_errstr(status));
14411                 goto fail;
14412         }
14413
14414         ret = true;
14415 fail:
14416         TALLOC_FREE(rec);
14417         return ret;
14418 }
14419
14420 static bool run_local_dbtrans(int dummy)
14421 {
14422         struct db_context *db;
14423         struct db_record *rec;
14424         NTSTATUS status;
14425         uint32_t initial;
14426         int res;
14427         TDB_DATA value;
14428
14429         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14430                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14431                      DBWRAP_FLAG_NONE);
14432         if (db == NULL) {
14433                 printf("Could not open transtest.db\n");
14434                 return false;
14435         }
14436
14437         res = dbwrap_transaction_start(db);
14438         if (res != 0) {
14439                 printf(__location__ "transaction_start failed\n");
14440                 return false;
14441         }
14442
14443         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14444         if (rec == NULL) {
14445                 printf(__location__ "fetch_lock failed\n");
14446                 return false;
14447         }
14448
14449         value = dbwrap_record_get_value(rec);
14450
14451         if (value.dptr == NULL) {
14452                 initial = 0;
14453                 status = dbwrap_record_store(
14454                         rec, make_tdb_data((uint8_t *)&initial,
14455                                            sizeof(initial)),
14456                         0);
14457                 if (!NT_STATUS_IS_OK(status)) {
14458                         printf(__location__ "store returned %s\n",
14459                                nt_errstr(status));
14460                         return false;
14461                 }
14462         }
14463
14464         TALLOC_FREE(rec);
14465
14466         res = dbwrap_transaction_commit(db);
14467         if (res != 0) {
14468                 printf(__location__ "transaction_commit failed\n");
14469                 return false;
14470         }
14471
14472         while (true) {
14473                 uint32_t val, val2;
14474                 int i;
14475
14476                 res = dbwrap_transaction_start(db);
14477                 if (res != 0) {
14478                         printf(__location__ "transaction_start failed\n");
14479                         break;
14480                 }
14481
14482                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14483                 if (!NT_STATUS_IS_OK(status)) {
14484                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14485                                nt_errstr(status));
14486                         break;
14487                 }
14488
14489                 for (i=0; i<10; i++) {
14490                         if (!dbtrans_inc(db)) {
14491                                 return false;
14492                         }
14493                 }
14494
14495                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14496                 if (!NT_STATUS_IS_OK(status)) {
14497                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14498                                nt_errstr(status));
14499                         break;
14500                 }
14501
14502                 if (val2 != val + 10) {
14503                         printf(__location__ "val=%d, val2=%d\n",
14504                                (int)val, (int)val2);
14505                         break;
14506                 }
14507
14508                 printf("val2=%d\r", val2);
14509
14510                 res = dbwrap_transaction_commit(db);
14511                 if (res != 0) {
14512                         printf(__location__ "transaction_commit failed\n");
14513                         break;
14514                 }
14515         }
14516
14517         TALLOC_FREE(db);
14518         return true;
14519 }
14520
14521 /*
14522  * Just a dummy test to be run under a debugger. There's no real way
14523  * to inspect the tevent_poll specific function from outside of
14524  * tevent_poll.c.
14525  */
14526
14527 static bool run_local_tevent_poll(int dummy)
14528 {
14529         struct tevent_context *ev;
14530         struct tevent_fd *fd1, *fd2;
14531         bool result = false;
14532
14533         ev = tevent_context_init_byname(NULL, "poll");
14534         if (ev == NULL) {
14535                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14536                 goto fail;
14537         }
14538
14539         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14540         if (fd1 == NULL) {
14541                 d_fprintf(stderr, "tevent_add_fd failed\n");
14542                 goto fail;
14543         }
14544         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14545         if (fd2 == NULL) {
14546                 d_fprintf(stderr, "tevent_add_fd failed\n");
14547                 goto fail;
14548         }
14549         TALLOC_FREE(fd2);
14550
14551         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14552         if (fd2 == NULL) {
14553                 d_fprintf(stderr, "tevent_add_fd failed\n");
14554                 goto fail;
14555         }
14556
14557         result = true;
14558 fail:
14559         TALLOC_FREE(ev);
14560         return result;
14561 }
14562
14563 static bool run_local_hex_encode_buf(int dummy)
14564 {
14565         char buf[17];
14566         uint8_t src[8];
14567         size_t i;
14568
14569         for (i=0; i<sizeof(src); i++) {
14570                 src[i] = i;
14571         }
14572         hex_encode_buf(buf, src, sizeof(src));
14573         if (strcmp(buf, "0001020304050607") != 0) {
14574                 return false;
14575         }
14576         hex_encode_buf(buf, NULL, 0);
14577         if (buf[0] != '\0') {
14578                 return false;
14579         }
14580         return true;
14581 }
14582
14583 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14584         "0.0.0.0",
14585         "::0",
14586         "1.2.3.1",
14587         "0.0.0.0",
14588         "0.0.0.0",
14589         "1.2.3.2",
14590         "1.2.3.3",
14591         "1.2.3.4",
14592         "1.2.3.5",
14593         "::0",
14594         "1.2.3.6",
14595         "1.2.3.7",
14596         "::0",
14597         "::0",
14598         "::0",
14599         "1.2.3.8",
14600         "1.2.3.9",
14601         "1.2.3.10",
14602         "1.2.3.11",
14603         "1.2.3.12",
14604         "1.2.3.13",
14605         "1001:1111:1111:1000:0:1111:1111:1111",
14606         "1.2.3.1",
14607         "1.2.3.2",
14608         "1.2.3.3",
14609         "1.2.3.12",
14610         "::0",
14611         "::0"
14612 };
14613
14614 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14615         "1.2.3.1",
14616         "1.2.3.2",
14617         "1.2.3.3",
14618         "1.2.3.4",
14619         "1.2.3.5",
14620         "1.2.3.6",
14621         "1.2.3.7",
14622         "1.2.3.8",
14623         "1.2.3.9",
14624         "1.2.3.10",
14625         "1.2.3.11",
14626         "1.2.3.12",
14627         "1.2.3.13",
14628         "1001:1111:1111:1000:0:1111:1111:1111"
14629 };
14630
14631 static bool run_local_remove_duplicate_addrs2(int dummy)
14632 {
14633         struct samba_sockaddr test_vector[28];
14634         size_t count, i;
14635
14636         /* Construct the sockaddr_storage test vector. */
14637         for (i = 0; i < 28; i++) {
14638                 struct addrinfo hints;
14639                 struct addrinfo *res = NULL;
14640                 int ret;
14641
14642                 memset(&hints, '\0', sizeof(hints));
14643                 hints.ai_flags = AI_NUMERICHOST;
14644                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14645                                 NULL,
14646                                 &hints,
14647                                 &res);
14648                 if (ret) {
14649                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14650                                 remove_duplicate_addrs2_test_strings_vector[i]);
14651                         return false;
14652                 }
14653                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14654                 memcpy(&test_vector[i].u.ss,
14655                         res->ai_addr,
14656                         res->ai_addrlen);
14657                 freeaddrinfo(res);
14658         }
14659
14660         count = remove_duplicate_addrs2(test_vector, i);
14661
14662         if (count != 14) {
14663                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14664                         count);
14665                 return false;
14666         }
14667
14668         for (i = 0; i < count; i++) {
14669                 char addr[INET6_ADDRSTRLEN];
14670
14671                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14672
14673                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14674                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14675                                 i,
14676                                 addr,
14677                                 remove_duplicate_addrs2_test_strings_result[i]);
14678                         return false;
14679                 }
14680         }
14681
14682         printf("run_local_remove_duplicate_addrs2: success\n");
14683         return true;
14684 }
14685
14686 static bool run_local_tdb_opener(int dummy)
14687 {
14688         TDB_CONTEXT *t;
14689         unsigned v = 0;
14690
14691         while (1) {
14692                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14693                              O_RDWR|O_CREAT, 0755);
14694                 if (t == NULL) {
14695                         perror("tdb_open failed");
14696                         return false;
14697                 }
14698                 tdb_close(t);
14699
14700                 v += 1;
14701                 printf("\r%u", v);
14702         }
14703         return true;
14704 }
14705
14706 static bool run_local_tdb_writer(int dummy)
14707 {
14708         TDB_CONTEXT *t;
14709         unsigned v = 0;
14710         TDB_DATA val;
14711
14712         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14713         if (t == 0) {
14714                 perror("tdb_open failed");
14715                 return 1;
14716         }
14717
14718         val.dptr = (uint8_t *)&v;
14719         val.dsize = sizeof(v);
14720
14721         while (1) {
14722                 TDB_DATA data;
14723                 int ret;
14724
14725                 ret = tdb_store(t, val, val, 0);
14726                 if (ret != 0) {
14727                         printf("%s\n", tdb_errorstr(t));
14728                 }
14729                 v += 1;
14730                 printf("\r%u", v);
14731
14732                 data = tdb_fetch(t, val);
14733                 if (data.dptr != NULL) {
14734                         SAFE_FREE(data.dptr);
14735                 }
14736         }
14737         return true;
14738 }
14739
14740 static bool run_local_canonicalize_path(int dummy)
14741 {
14742         const char *src[] = {
14743                         "/foo/..",
14744                         "/..",
14745                         "/foo/bar/../baz",
14746                         "/foo/././",
14747                         "/../foo",
14748                         ".././././",
14749                         ".././././../../../boo",
14750                         "./..",
14751                         "/",
14752                         "/../../",
14753                         "/foo/../",
14754                         "/./././",
14755                         "/./././.",
14756                         "/.../././.",
14757                         "/./././.foo",
14758                         "/./././.foo.",
14759                         "/./././foo.",
14760                         "/foo/bar/..",
14761                         "/foo/bar/../baz/",
14762                         "////////////////",
14763                         "/////////./././././.",
14764                         "/./.././../.boo/../baz",
14765                         "/a/component/path",
14766                         "/a/component/path/",
14767                         "/a/component/path/..",
14768                         "/a/component/../path/",
14769                         "///a/./././///component/../////path/",
14770                         NULL
14771                         };
14772         const char *dst[] = {
14773                         "/",
14774                         "/",
14775                         "/foo/baz",
14776                         "/foo",
14777                         "/foo",
14778                         "/",
14779                         "/boo",
14780                         "/",
14781                         "/",
14782                         "/",
14783                         "/",
14784                         "/",
14785                         "/",
14786                         "/...",
14787                         "/.foo",
14788                         "/.foo.",
14789                         "/foo.",
14790                         "/foo",
14791                         "/foo/baz",
14792                         "/",
14793                         "/",
14794                         "/baz",
14795                         "/a/component/path",
14796                         "/a/component/path",
14797                         "/a/component",
14798                         "/a/path",
14799                         "/a/path",
14800                         NULL
14801                         };
14802         unsigned int i;
14803
14804         for (i = 0; src[i] != NULL; i++) {
14805                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14806                 if (d == NULL) {
14807                         perror("talloc fail\n");
14808                         return false;
14809                 }
14810                 if (strcmp(d, dst[i]) != 0) {
14811                         d_fprintf(stderr,
14812                                 "canonicalize mismatch %s -> %s != %s",
14813                                 src[i], d, dst[i]);
14814                         return false;
14815                 }
14816                 talloc_free(d);
14817         }
14818         return true;
14819 }
14820 struct session_setup_nt1_truncated_state {
14821         uint16_t vwv[13];
14822         uint8_t bytes[20];
14823 };
14824
14825 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14826
14827 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14828                 TALLOC_CTX *mem_ctx,
14829                 struct tevent_context *ev,
14830                 struct smbXcli_conn *conn)
14831 {
14832         uint16_t *vwv = NULL;
14833         uint8_t *bytes = NULL;
14834         const char *pass = "12345678";
14835         const char *uname = "z";
14836         struct session_setup_nt1_truncated_state *state = NULL;
14837         struct tevent_req *req = NULL;
14838         struct tevent_req *subreq = NULL;
14839
14840         req = tevent_req_create(mem_ctx,
14841                                 &state,
14842                                 struct session_setup_nt1_truncated_state);
14843         if (req == NULL) {
14844                 return NULL;
14845         }
14846         vwv = &state->vwv[0];
14847         bytes = &state->bytes[0];
14848
14849         SCVAL(vwv+0,  0, 0xff);
14850         SCVAL(vwv+0,  1, 0);
14851         SSVAL(vwv+1,  0, 0);
14852         SSVAL(vwv+2,  0, 8192);
14853         SSVAL(vwv+3,  0, 2);
14854         SSVAL(vwv+4,  0, 1);
14855         SIVAL(vwv+5,  0, 0);
14856         SSVAL(vwv+7,  0, strlen(pass)); /* OEMPasswordLen */
14857         SSVAL(vwv+8,  0, 0); /* UnicodePasswordLen */
14858         SSVAL(vwv+9,  0, 0); /* reserved */
14859         SSVAL(vwv+10, 0, 0); /* reserved */
14860         SIVAL(vwv+11, 0, CAP_STATUS32);
14861
14862         memcpy(bytes, pass, strlen(pass));
14863         bytes += strlen(pass);
14864         memcpy(bytes, uname, strlen(uname)+1);
14865
14866         subreq = smb1cli_req_send(state, ev, conn,
14867                                   SMBsesssetupX,
14868                                   0, /*  additional_flags */
14869                                   0, /*  clear_flags */
14870                                   0, /*  additional_flags2 */
14871                                   0, /*  clear_flags2 */
14872                                   10000, /* timeout_msec */
14873                                   getpid(),
14874                                   NULL, /* tcon */
14875                                   NULL, /* session */
14876                                   13, /* wct */
14877                                   state->vwv,
14878                                   strlen(pass), /* Truncate length at password. */
14879                                   state->bytes);
14880         if (tevent_req_nomem(subreq, req)) {
14881                 return tevent_req_post(req, ev);
14882         }
14883         tevent_req_set_callback(subreq,
14884                                 smb1_session_setup_nt1_truncated_done,
14885                                 req);
14886         return req;
14887 }
14888
14889 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14890 {
14891         struct tevent_req *req =
14892                 tevent_req_callback_data(subreq,
14893                 struct tevent_req);
14894         struct session_setup_nt1_truncated_state *state =
14895                 tevent_req_data(req,
14896                 struct session_setup_nt1_truncated_state);
14897         NTSTATUS status;
14898         struct smb1cli_req_expected_response expected[] = {
14899         {
14900                 .status = NT_STATUS_OK,
14901                 .wct    = 3,
14902         },
14903         };
14904
14905         status = smb1cli_req_recv(subreq, state,
14906                                   NULL,
14907                                   NULL,
14908                                   NULL,
14909                                   NULL,
14910                                   NULL, /* pvwv_offset */
14911                                   NULL,
14912                                   NULL,
14913                                   NULL, /* pbytes_offset */
14914                                   NULL,
14915                                   expected, ARRAY_SIZE(expected));
14916         TALLOC_FREE(subreq);
14917         if (tevent_req_nterror(req, status)) {
14918                 return;
14919         }
14920         tevent_req_done(req);
14921 }
14922
14923 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14924 {
14925         return tevent_req_simple_recv_ntstatus(req);
14926 }
14927
14928 static bool run_smb1_truncated_sesssetup(int dummy)
14929 {
14930         struct tevent_context *ev;
14931         struct tevent_req *req;
14932         struct smbXcli_conn *conn;
14933         struct sockaddr_storage ss;
14934         NTSTATUS status;
14935         int fd;
14936         bool ok;
14937
14938         printf("Starting send truncated SMB1 sesssetup.\n");
14939
14940         ok = resolve_name(host, &ss, 0x20, true);
14941         if (!ok) {
14942                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14943                 return false;
14944         }
14945
14946         status = open_socket_out(&ss, 445, 10000, &fd);
14947         if (!NT_STATUS_IS_OK(status)) {
14948                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14949                           nt_errstr(status));
14950                 return false;
14951         }
14952
14953         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14954                                    NULL, 0, NULL);
14955         if (conn == NULL) {
14956                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14957                 return false;
14958         }
14959
14960         status = smbXcli_negprot(conn,
14961                                  0,
14962                                  PROTOCOL_NT1,
14963                                  PROTOCOL_NT1,
14964                                  NULL,
14965                                  NULL,
14966                                  NULL);
14967         if (!NT_STATUS_IS_OK(status)) {
14968                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14969                 return false;
14970         }
14971
14972         ev = samba_tevent_context_init(talloc_tos());
14973         if (ev == NULL) {
14974                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14975                 return false;
14976         }
14977
14978         req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14979         if (req == NULL) {
14980                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14981                 return false;
14982         }
14983
14984         ok = tevent_req_poll_ntstatus(req, ev, &status);
14985         if (!ok) {
14986                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14987                         nt_errstr(status));
14988                 return false;
14989         }
14990
14991         status = smb1_session_setup_nt1_truncated_recv(req);
14992         if (!NT_STATUS_IS_OK(status)) {
14993                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14994                           "%s, expected NT_STATUS_OK\n",
14995                           nt_errstr(status));
14996                 return false;
14997         }
14998
14999         TALLOC_FREE(conn);
15000         return true;
15001 }
15002
15003 struct smb1_negotiate_exit_state {
15004         int dummy;
15005 };
15006
15007 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15008
15009 static struct tevent_req *smb1_negotiate_exit_send(
15010                 TALLOC_CTX *mem_ctx,
15011                 struct tevent_context *ev,
15012                 struct smbXcli_conn *conn)
15013 {
15014         struct smb1_negotiate_exit_state *state = NULL;
15015         struct tevent_req *req = NULL;
15016         struct tevent_req *subreq = NULL;
15017
15018         req = tevent_req_create(mem_ctx,
15019                                 &state,
15020                                 struct smb1_negotiate_exit_state);
15021         if (req == NULL) {
15022                 return NULL;
15023         }
15024         subreq = smb1cli_req_send(state, ev, conn,
15025                                   SMBexit,
15026                                   0, /*  additional_flags */
15027                                   0, /*  clear_flags */
15028                                   0, /*  additional_flags2 */
15029                                   0, /*  clear_flags2 */
15030                                   10000, /* timeout_msec */
15031                                   getpid(),
15032                                   NULL, /* tcon */
15033                                   NULL, /* session */
15034                                   0, /* wct */
15035                                   NULL,
15036                                   0,
15037                                   NULL);
15038         if (tevent_req_nomem(subreq, req)) {
15039                 return tevent_req_post(req, ev);
15040         }
15041         tevent_req_set_callback(subreq,
15042                                 smb1_negotiate_exit_done,
15043                                 req);
15044         return req;
15045 }
15046
15047 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15048 {
15049         struct tevent_req *req =
15050                 tevent_req_callback_data(subreq,
15051                 struct tevent_req);
15052         struct smb1_negotiate_exit_state *state =
15053                 tevent_req_data(req,
15054                 struct smb1_negotiate_exit_state);
15055         NTSTATUS status;
15056         struct smb1cli_req_expected_response expected[] = {
15057         {
15058                 .status = NT_STATUS_OK,
15059                 .wct    = 0,
15060         },
15061         };
15062
15063         status = smb1cli_req_recv(subreq, state,
15064                                   NULL,
15065                                   NULL,
15066                                   NULL,
15067                                   NULL,
15068                                   NULL, /* pvwv_offset */
15069                                   NULL,
15070                                   NULL,
15071                                   NULL, /* pbytes_offset */
15072                                   NULL,
15073                                   expected, ARRAY_SIZE(expected));
15074         TALLOC_FREE(subreq);
15075         if (tevent_req_nterror(req, status)) {
15076                 return;
15077         }
15078         tevent_req_done(req);
15079 }
15080
15081 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15082 {
15083         return tevent_req_simple_recv_ntstatus(req);
15084 }
15085
15086 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15087                          struct tevent_context *ev,
15088                          struct smbXcli_conn *conn)
15089 {
15090         struct tevent_req *req;
15091         bool ok;
15092         NTSTATUS status;
15093         NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15094
15095         req = smb1_negotiate_exit_send(ev, ev, conn);
15096         if (req == NULL) {
15097                 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15098                 return false;
15099         }
15100
15101         ok = tevent_req_poll_ntstatus(req, ev, &status);
15102         if (!ok) {
15103                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15104                         nt_errstr(status));
15105                 return false;
15106         }
15107
15108         status = smb1_negotiate_exit_recv(req);
15109         if (!NT_STATUS_EQUAL(status, expected_status)) {
15110                 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15111                           "%s, expected ERRSRV, ERRinvnid\n",
15112                           nt_errstr(status));
15113                 return false;
15114         }
15115         return true;
15116 }
15117
15118 static bool run_smb1_negotiate_exit(int dummy)
15119 {
15120         struct tevent_context *ev;
15121         struct smbXcli_conn *conn;
15122         struct sockaddr_storage ss;
15123         NTSTATUS status;
15124         int fd;
15125         bool ok;
15126
15127         printf("Starting send SMB1 negotiate+exit.\n");
15128
15129         ok = resolve_name(host, &ss, 0x20, true);
15130         if (!ok) {
15131                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15132                 return false;
15133         }
15134
15135         status = open_socket_out(&ss, 445, 10000, &fd);
15136         if (!NT_STATUS_IS_OK(status)) {
15137                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15138                           nt_errstr(status));
15139                 return false;
15140         }
15141
15142         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15143                                    NULL, 0, NULL);
15144         if (conn == NULL) {
15145                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15146                 return false;
15147         }
15148
15149         status = smbXcli_negprot(conn,
15150                                  0,
15151                                  PROTOCOL_NT1,
15152                                  PROTOCOL_NT1,
15153                                  NULL,
15154                                  NULL,
15155                                  NULL);
15156         if (!NT_STATUS_IS_OK(status)) {
15157                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15158                 return false;
15159         }
15160
15161         ev = samba_tevent_context_init(talloc_tos());
15162         if (ev == NULL) {
15163                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15164                 return false;
15165         }
15166
15167         /*
15168          * Call do_smb1_exit twice to catch a server crash, the
15169          * server sends the first return code then crashes.
15170          */
15171         ok = do_smb1_exit(ev, ev, conn);
15172         if (!ok) {
15173                 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15174                 return false;
15175         }
15176         ok = do_smb1_exit(ev, ev, conn);
15177         if (!ok) {
15178                 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15179                 return false;
15180         }
15181
15182         TALLOC_FREE(conn);
15183         return true;
15184 }
15185
15186 static bool run_smb1_negotiate_tcon(int dummy)
15187 {
15188         struct cli_state *cli = NULL;
15189         uint16_t cnum = 0;
15190         uint16_t max_xmit = 0;
15191         NTSTATUS status;
15192
15193         printf("Starting send SMB1 negotiate+tcon.\n");
15194         cli = open_nbt_connection();
15195         if (cli == NULL) {
15196                 d_fprintf(stderr, "open_nbt_connection failed!\n");
15197                 return false;
15198         }
15199         smbXcli_conn_set_sockopt(cli->conn, sockops);
15200
15201         status = smbXcli_negprot(cli->conn,
15202                                  0,
15203                                  PROTOCOL_NT1,
15204                                  PROTOCOL_NT1,
15205                                  NULL,
15206                                  NULL,
15207                                  NULL);
15208         if (!NT_STATUS_IS_OK(status)) {
15209                 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15210                         nt_errstr(status));
15211                 return false;
15212         }
15213         status = cli_raw_tcon(cli,
15214                               share,
15215                               "",
15216                               "?????",
15217                               &max_xmit,
15218                               &cnum);
15219         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15220                 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15221                         "(should get NT_STATUS_ACCESS_DENIED)!\n",
15222                         nt_errstr(status));
15223                 return false;
15224         }
15225         return true;
15226 }
15227
15228 static bool run_ign_bad_negprot(int dummy)
15229 {
15230         struct tevent_context *ev;
15231         struct tevent_req *req;
15232         struct smbXcli_conn *conn;
15233         struct sockaddr_storage ss;
15234         NTSTATUS status;
15235         int fd;
15236         bool ok;
15237
15238         printf("starting ignore bad negprot\n");
15239
15240         ok = resolve_name(host, &ss, 0x20, true);
15241         if (!ok) {
15242                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15243                 return false;
15244         }
15245
15246         status = open_socket_out(&ss, 445, 10000, &fd);
15247         if (!NT_STATUS_IS_OK(status)) {
15248                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15249                           nt_errstr(status));
15250                 return false;
15251         }
15252
15253         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15254                                    NULL, 0, NULL);
15255         if (conn == NULL) {
15256                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15257                 return false;
15258         }
15259
15260         status = smbXcli_negprot(conn,
15261                                  0,
15262                                  PROTOCOL_CORE,
15263                                  PROTOCOL_CORE,
15264                                  NULL,
15265                                  NULL,
15266                                  NULL);
15267         if (NT_STATUS_IS_OK(status)) {
15268                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15269                 return false;
15270         }
15271
15272         ev = samba_tevent_context_init(talloc_tos());
15273         if (ev == NULL) {
15274                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15275                 return false;
15276         }
15277
15278         req = smb1cli_session_setup_nt1_send(
15279                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15280                 data_blob_null, data_blob_null, 0x40,
15281                 "Windows 2000 2195", "Windows 2000 5.0");
15282         if (req == NULL) {
15283                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15284                 return false;
15285         }
15286
15287         ok = tevent_req_poll_ntstatus(req, ev, &status);
15288         if (!ok) {
15289                 d_fprintf(stderr, "tevent_req_poll failed\n");
15290                 return false;
15291         }
15292
15293         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15294                                                 NULL, NULL);
15295         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15296                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15297                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
15298                           nt_errstr(status));
15299                 return false;
15300         }
15301
15302         TALLOC_FREE(conn);
15303
15304         printf("starting ignore bad negprot\n");
15305
15306         return true;
15307 }
15308
15309
15310 static double create_procs(bool (*fn)(int), bool *result)
15311 {
15312         int i, status;
15313         volatile pid_t *child_status;
15314         volatile bool *child_status_out;
15315         int synccount;
15316         int tries = 8;
15317         struct timeval start;
15318
15319         synccount = 0;
15320
15321         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15322         if (!child_status) {
15323                 printf("Failed to setup shared memory\n");
15324                 return -1;
15325         }
15326
15327         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15328         if (!child_status_out) {
15329                 printf("Failed to setup result status shared memory\n");
15330                 return -1;
15331         }
15332
15333         for (i = 0; i < torture_nprocs; i++) {
15334                 child_status[i] = 0;
15335                 child_status_out[i] = True;
15336         }
15337
15338         start = timeval_current();
15339
15340         for (i=0;i<torture_nprocs;i++) {
15341                 procnum = i;
15342                 if (fork() == 0) {
15343                         pid_t mypid = getpid();
15344                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15345
15346                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
15347
15348                         while (1) {
15349                                 if (torture_open_connection(&current_cli, i)) break;
15350                                 if (tries-- == 0) {
15351                                         printf("pid %d failed to start\n", (int)getpid());
15352                                         _exit(1);
15353                                 }
15354                                 smb_msleep(10);
15355                         }
15356
15357                         child_status[i] = getpid();
15358
15359                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15360
15361                         child_status_out[i] = fn(i);
15362                         _exit(0);
15363                 }
15364         }
15365
15366         do {
15367                 synccount = 0;
15368                 for (i=0;i<torture_nprocs;i++) {
15369                         if (child_status[i]) synccount++;
15370                 }
15371                 if (synccount == torture_nprocs) break;
15372                 smb_msleep(10);
15373         } while (timeval_elapsed(&start) < 30);
15374
15375         if (synccount != torture_nprocs) {
15376                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15377                 *result = False;
15378                 return timeval_elapsed(&start);
15379         }
15380
15381         /* start the client load */
15382         start = timeval_current();
15383
15384         for (i=0;i<torture_nprocs;i++) {
15385                 child_status[i] = 0;
15386         }
15387
15388         printf("%d clients started\n", torture_nprocs);
15389
15390         for (i=0;i<torture_nprocs;i++) {
15391                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15392         }
15393
15394         printf("\n");
15395
15396         for (i=0;i<torture_nprocs;i++) {
15397                 if (!child_status_out[i]) {
15398                         *result = False;
15399                 }
15400         }
15401         return timeval_elapsed(&start);
15402 }
15403
15404 #define FLAG_MULTIPROC 1
15405
15406 static struct {
15407         const char *name;
15408         bool (*fn)(int);
15409         unsigned flags;
15410 } torture_ops[] = {
15411         {
15412                 .name = "FDPASS",
15413                 .fn   = run_fdpasstest,
15414         },
15415         {
15416                 .name = "LOCK1",
15417                 .fn   = run_locktest1,
15418         },
15419         {
15420                 .name = "LOCK2",
15421                 .fn   =  run_locktest2,
15422         },
15423         {
15424                 .name = "LOCK3",
15425                 .fn   =  run_locktest3,
15426         },
15427         {
15428                 .name = "LOCK4",
15429                 .fn   =  run_locktest4,
15430         },
15431         {
15432                 .name = "LOCK5",
15433                 .fn   =  run_locktest5,
15434         },
15435         {
15436                 .name = "LOCK6",
15437                 .fn   =  run_locktest6,
15438         },
15439         {
15440                 .name = "LOCK7",
15441                 .fn   =  run_locktest7,
15442         },
15443         {
15444                 .name = "LOCK8",
15445                 .fn   =  run_locktest8,
15446         },
15447         {
15448                 .name = "LOCK9A",
15449                 .fn   =  run_locktest9a,
15450         },
15451         {
15452                 .name = "LOCK9B",
15453                 .fn   =  run_locktest9b,
15454         },
15455         {
15456                 .name = "LOCK10",
15457                 .fn   =  run_locktest10,
15458         },
15459         {
15460                 .name = "LOCK11",
15461                 .fn   =  run_locktest11,
15462         },
15463         {
15464                 .name = "LOCK12",
15465                 .fn   =  run_locktest12,
15466         },
15467         {
15468                 .name = "LOCK13",
15469                 .fn   =  run_locktest13,
15470         },
15471         {
15472                 .name = "UNLINK",
15473                 .fn   = run_unlinktest,
15474         },
15475         {
15476                 .name = "BROWSE",
15477                 .fn   = run_browsetest,
15478         },
15479         {
15480                 .name = "ATTR",
15481                 .fn   =   run_attrtest,
15482         },
15483         {
15484                 .name = "TRANS2",
15485                 .fn   = run_trans2test,
15486         },
15487         {
15488                 .name  = "MAXFID",
15489                 .fn    = run_maxfidtest,
15490                 .flags = FLAG_MULTIPROC,
15491         },
15492         {
15493                 .name  = "TORTURE",
15494                 .fn    = run_torture,
15495                 .flags = FLAG_MULTIPROC,
15496         },
15497         {
15498                 .name  = "RANDOMIPC",
15499                 .fn    = run_randomipc,
15500         },
15501         {
15502                 .name  = "NEGNOWAIT",
15503                 .fn    = run_negprot_nowait,
15504         },
15505         {
15506                 .name  = "NBENCH",
15507                 .fn    =  run_nbench,
15508         },
15509         {
15510                 .name  = "NBENCH2",
15511                 .fn    = run_nbench2,
15512         },
15513         {
15514                 .name  = "OPLOCK1",
15515                 .fn    =  run_oplock1,
15516         },
15517         {
15518                 .name  = "OPLOCK2",
15519                 .fn    =  run_oplock2,
15520         },
15521         {
15522                 .name  = "OPLOCK4",
15523                 .fn    =  run_oplock4,
15524         },
15525 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15526         {
15527                 .name  = "OPLOCK5",
15528                 .fn    =  run_oplock5,
15529         },
15530 #endif
15531         {
15532                 .name  = "DIR",
15533                 .fn    =  run_dirtest,
15534         },
15535         {
15536                 .name  = "DIR1",
15537                 .fn    =  run_dirtest1,
15538         },
15539         {
15540                 .name  = "DIR-CREATETIME",
15541                 .fn    =  run_dir_createtime,
15542         },
15543         {
15544                 .name  = "DENY1",
15545                 .fn    =  torture_denytest1,
15546         },
15547         {
15548                 .name  = "DENY2",
15549                 .fn    =  torture_denytest2,
15550         },
15551         {
15552                 .name  = "TCON",
15553                 .fn    =  run_tcon_test,
15554         },
15555         {
15556                 .name  = "TCONDEV",
15557                 .fn    =  run_tcon_devtype_test,
15558         },
15559         {
15560                 .name  = "RW1",
15561                 .fn    =  run_readwritetest,
15562         },
15563         {
15564                 .name  = "RW2",
15565                 .fn    =  run_readwritemulti,
15566                 .flags = FLAG_MULTIPROC
15567         },
15568         {
15569                 .name  = "RW3",
15570                 .fn    =  run_readwritelarge,
15571         },
15572         {
15573                 .name  = "RW-SIGNING",
15574                 .fn    =  run_readwritelarge_signtest,
15575         },
15576         {
15577                 .name  = "OPEN",
15578                 .fn    = run_opentest,
15579         },
15580         {
15581                 .name  = "POSIX",
15582                 .fn    = run_simple_posix_open_test,
15583         },
15584         {
15585                 .name  = "POSIX-APPEND",
15586                 .fn    = run_posix_append,
15587         },
15588         {
15589                 .name  = "POSIX-SYMLINK-ACL",
15590                 .fn    = run_acl_symlink_test,
15591         },
15592         {
15593                 .name  = "POSIX-SYMLINK-EA",
15594                 .fn    = run_ea_symlink_test,
15595         },
15596         {
15597                 .name  = "POSIX-STREAM-DELETE",
15598                 .fn    = run_posix_stream_delete,
15599         },
15600         {
15601                 .name  = "POSIX-OFD-LOCK",
15602                 .fn    = run_posix_ofd_lock_test,
15603         },
15604         {
15605                 .name  = "POSIX-BLOCKING-LOCK",
15606                 .fn    = run_posix_blocking_lock,
15607         },
15608         {
15609                 .name  = "POSIX-MKDIR",
15610                 .fn    = run_posix_mkdir_test,
15611         },
15612         {
15613                 .name  = "POSIX-ACL-OPLOCK",
15614                 .fn    = run_posix_acl_oplock_test,
15615         },
15616         {
15617                 .name  = "POSIX-ACL-SHAREROOT",
15618                 .fn    = run_posix_acl_shareroot_test,
15619         },
15620         {
15621                 .name  = "POSIX-LS-WILDCARD",
15622                 .fn    = run_posix_ls_wildcard_test,
15623         },
15624         {
15625                 .name  = "POSIX-LS-SINGLE",
15626                 .fn    = run_posix_ls_single_test,
15627         },
15628         {
15629                 .name  = "POSIX-READLINK",
15630                 .fn    = run_posix_readlink_test,
15631         },
15632         {
15633                 .name  = "POSIX-STAT",
15634                 .fn    = run_posix_stat_test,
15635         },
15636         {
15637                 .name  = "POSIX-SYMLINK-PARENT",
15638                 .fn    = run_posix_symlink_parent_test,
15639         },
15640         {
15641                 .name  = "POSIX-SYMLINK-CHMOD",
15642                 .fn    = run_posix_symlink_chmod_test,
15643         },
15644         {
15645                 .name  = "POSIX-SYMLINK-RENAME",
15646                 .fn    = run_posix_symlink_rename_test,
15647         },
15648         {
15649                 .name  = "POSIX-DIR-DEFAULT-ACL",
15650                 .fn    = run_posix_dir_default_acl_test,
15651         },
15652         {
15653                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15654                 .fn    = run_posix_symlink_getpathinfo_test,
15655         },
15656         {
15657                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15658                 .fn    = run_posix_symlink_setpathinfo_test,
15659         },
15660         {
15661                 .name  = "WINDOWS-BAD-SYMLINK",
15662                 .fn    = run_symlink_open_test,
15663         },
15664         {
15665                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15666                 .fn    = run_smb1_wild_mangle_unlink_test,
15667         },
15668         {
15669                 .name  = "SMB1-WILD-MANGLE-RENAME",
15670                 .fn    = run_smb1_wild_mangle_rename_test,
15671         },
15672         {
15673                 .name  = "CASE-INSENSITIVE-CREATE",
15674                 .fn    = run_case_insensitive_create,
15675         },
15676         {
15677                 .name  = "ASYNC-ECHO",
15678                 .fn    = run_async_echo,
15679         },
15680         {
15681                 .name  = "UID-REGRESSION-TEST",
15682                 .fn    = run_uid_regression_test,
15683         },
15684         {
15685                 .name  = "SHORTNAME-TEST",
15686                 .fn    = run_shortname_test,
15687         },
15688         {
15689                 .name  = "ADDRCHANGE",
15690                 .fn    = run_addrchange,
15691         },
15692 #if 1
15693         {
15694                 .name  = "OPENATTR",
15695                 .fn    = run_openattrtest,
15696         },
15697 #endif
15698         {
15699                 .name  = "XCOPY",
15700                 .fn    = run_xcopy,
15701         },
15702         {
15703                 .name  = "RENAME",
15704                 .fn    = run_rename,
15705         },
15706         {
15707                 .name  = "RENAME-ACCESS",
15708                 .fn    = run_rename_access,
15709         },
15710         {
15711                 .name  = "OWNER-RIGHTS",
15712                 .fn    = run_owner_rights,
15713         },
15714         {
15715                 .name  = "DELETE",
15716                 .fn    = run_deletetest,
15717         },
15718         {
15719                 .name  = "DELETE-STREAM",
15720                 .fn    = run_delete_stream,
15721         },
15722         {
15723                 .name  = "DELETE-PRINT",
15724                 .fn    = run_delete_print_test,
15725         },
15726         {
15727                 .name  = "DELETE-LN",
15728                 .fn    = run_deletetest_ln,
15729         },
15730         {
15731                 .name  = "PROPERTIES",
15732                 .fn    = run_properties,
15733         },
15734         {
15735                 .name  = "MANGLE",
15736                 .fn    = torture_mangle,
15737         },
15738         {
15739                 .name  = "MANGLE1",
15740                 .fn    = run_mangle1,
15741         },
15742         {
15743                 .name  = "MANGLE-ILLEGAL",
15744                 .fn    = run_mangle_illegal,
15745         },
15746         {
15747                 .name  = "W2K",
15748                 .fn    = run_w2ktest,
15749         },
15750         {
15751                 .name  = "TRANS2SCAN",
15752                 .fn    = torture_trans2_scan,
15753         },
15754         {
15755                 .name  = "NTTRANSSCAN",
15756                 .fn    = torture_nttrans_scan,
15757         },
15758         {
15759                 .name  = "UTABLE",
15760                 .fn    = torture_utable,
15761         },
15762         {
15763                 .name  = "CASETABLE",
15764                 .fn    = torture_casetable,
15765         },
15766         {
15767                 .name  = "ERRMAPEXTRACT",
15768                 .fn    = run_error_map_extract,
15769         },
15770         {
15771                 .name  = "PIPE_NUMBER",
15772                 .fn    = run_pipe_number,
15773         },
15774         {
15775                 .name  = "TCON2",
15776                 .fn    =  run_tcon2_test,
15777         },
15778         {
15779                 .name  = "IOCTL",
15780                 .fn    =  torture_ioctl_test,
15781         },
15782         {
15783                 .name  = "CHKPATH",
15784                 .fn    =  torture_chkpath_test,
15785         },
15786         {
15787                 .name  = "FDSESS",
15788                 .fn    = run_fdsesstest,
15789         },
15790         {
15791                 .name  = "EATEST",
15792                 .fn    = run_eatest,
15793         },
15794         {
15795                 .name  = "SESSSETUP_BENCH",
15796                 .fn    = run_sesssetup_bench,
15797         },
15798         {
15799                 .name  = "CHAIN1",
15800                 .fn    = run_chain1,
15801         },
15802         {
15803                 .name  = "CHAIN2",
15804                 .fn    = run_chain2,
15805         },
15806         {
15807                 .name  = "CHAIN3",
15808                 .fn    = run_chain3,
15809         },
15810         {
15811                 .name  = "WINDOWS-WRITE",
15812                 .fn    = run_windows_write,
15813         },
15814         {
15815                 .name  = "LARGE_READX",
15816                 .fn    = run_large_readx,
15817         },
15818         {
15819                 .name  = "MSDFS-ATTRIBUTE",
15820                 .fn    = run_msdfs_attribute,
15821         },
15822         {
15823                 .name  = "NTTRANS-CREATE",
15824                 .fn    = run_nttrans_create,
15825         },
15826         {
15827                 .name  = "NTTRANS-FSCTL",
15828                 .fn    = run_nttrans_fsctl,
15829         },
15830         {
15831                 .name  = "CLI_ECHO",
15832                 .fn    = run_cli_echo,
15833         },
15834         {
15835                 .name  = "CLI_SPLICE",
15836                 .fn    = run_cli_splice,
15837         },
15838         {
15839                 .name  = "TLDAP",
15840                 .fn    = run_tldap,
15841         },
15842         {
15843                 .name  = "STREAMERROR",
15844                 .fn    = run_streamerror,
15845         },
15846         {
15847                 .name  = "NOTIFY-BENCH",
15848                 .fn    = run_notify_bench,
15849         },
15850         {
15851                 .name  = "NOTIFY-BENCH2",
15852                 .fn    = run_notify_bench2,
15853         },
15854         {
15855                 .name  = "NOTIFY-BENCH3",
15856                 .fn    = run_notify_bench3,
15857         },
15858         {
15859                 .name  = "BAD-NBT-SESSION",
15860                 .fn    = run_bad_nbt_session,
15861         },
15862         {
15863                 .name  = "IGN-BAD-NEGPROT",
15864                 .fn    = run_ign_bad_negprot,
15865         },
15866         {
15867                 .name  = "SMB-ANY-CONNECT",
15868                 .fn    = run_smb_any_connect,
15869         },
15870         {
15871                 .name  = "NOTIFY-ONLINE",
15872                 .fn    = run_notify_online,
15873         },
15874         {
15875                 .name  = "SMB2-BASIC",
15876                 .fn    = run_smb2_basic,
15877         },
15878         {
15879                 .name  = "SMB2-NEGPROT",
15880                 .fn    = run_smb2_negprot,
15881         },
15882         {
15883                 .name  = "SMB2-ANONYMOUS",
15884                 .fn    = run_smb2_anonymous,
15885         },
15886         {
15887                 .name  = "SMB2-SESSION-RECONNECT",
15888                 .fn    = run_smb2_session_reconnect,
15889         },
15890         {
15891                 .name  = "SMB2-TCON-DEPENDENCE",
15892                 .fn    = run_smb2_tcon_dependence,
15893         },
15894         {
15895                 .name  = "SMB2-MULTI-CHANNEL",
15896                 .fn    = run_smb2_multi_channel,
15897         },
15898         {
15899                 .name  = "SMB2-SESSION-REAUTH",
15900                 .fn    = run_smb2_session_reauth,
15901         },
15902         {
15903                 .name  = "SMB2-FTRUNCATE",
15904                 .fn    = run_smb2_ftruncate,
15905         },
15906         {
15907                 .name  = "SMB2-DIR-FSYNC",
15908                 .fn    = run_smb2_dir_fsync,
15909         },
15910         {
15911                 .name  = "SMB2-PATH-SLASH",
15912                 .fn    = run_smb2_path_slash,
15913         },
15914         {
15915                 .name  = "SMB1-SYSTEM-SECURITY",
15916                 .fn    = run_smb1_system_security,
15917         },
15918         {
15919                 .name  = "SMB2-SACL",
15920                 .fn    = run_smb2_sacl,
15921         },
15922         {
15923                 .name  = "SMB2-QUOTA1",
15924                 .fn    = run_smb2_quota1,
15925         },
15926         {
15927                 .name  = "SMB2-INVALID-PIPENAME",
15928                 .fn    = run_smb2_invalid_pipename,
15929         },
15930         {
15931                 .name  = "SMB2-STREAM-ACL",
15932                 .fn    = run_smb2_stream_acl,
15933         },
15934         {
15935                 .name  = "SMB2-LIST-DIR-ASYNC",
15936                 .fn    = run_list_dir_async_test,
15937         },
15938         {
15939                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15940                 .fn    = run_delete_on_close_non_empty,
15941         },
15942         {
15943                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15944                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15945         },
15946         {
15947                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15948                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15949         },
15950         {
15951                 .name  = "SMB2-DFS-PATHS",
15952                 .fn    = run_smb2_dfs_paths,
15953         },
15954         {
15955                 .name  = "SMB2-NON-DFS-SHARE",
15956                 .fn    = run_smb2_non_dfs_share,
15957         },
15958         {
15959                 .name  = "SMB2-DFS-SHARE-NON-DFS-PATH",
15960                 .fn    = run_smb2_dfs_share_non_dfs_path,
15961         },
15962         {
15963                 .name  = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15964                 .fn    = run_smb2_dfs_filename_leading_backslash,
15965         },
15966         {
15967                 .name  = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15968                 .fn    = run_smb2_pipe_read_async_disconnect,
15969         },
15970         {
15971                 .name  = "SMB1-TRUNCATED-SESSSETUP",
15972                 .fn    = run_smb1_truncated_sesssetup,
15973         },
15974         {
15975                 .name  = "SMB1-NEGOTIATE-EXIT",
15976                 .fn    = run_smb1_negotiate_exit,
15977         },
15978         {
15979                 .name  = "SMB1-NEGOTIATE-TCON",
15980                 .fn    = run_smb1_negotiate_tcon,
15981         },
15982         {
15983                 .name  = "SMB1-DFS-PATHS",
15984                 .fn    = run_smb1_dfs_paths,
15985         },
15986         {
15987                 .name  = "SMB1-DFS-SEARCH-PATHS",
15988                 .fn    = run_smb1_dfs_search_paths,
15989         },
15990         {
15991                 .name  = "SMB1-DFS-OPERATIONS",
15992                 .fn    = run_smb1_dfs_operations,
15993         },
15994         {
15995                 .name  = "SMB1-DFS-BADPATH",
15996                 .fn    = run_smb1_dfs_check_badpath,
15997         },
15998         {
15999                 .name  = "CLEANUP1",
16000                 .fn    = run_cleanup1,
16001         },
16002         {
16003                 .name  = "CLEANUP2",
16004                 .fn    = run_cleanup2,
16005         },
16006         {
16007                 .name  = "CLEANUP4",
16008                 .fn    = run_cleanup4,
16009         },
16010         {
16011                 .name  = "OPLOCK-CANCEL",
16012                 .fn    = run_oplock_cancel,
16013         },
16014         {
16015                 .name  = "PIDHIGH",
16016                 .fn    = run_pidhigh,
16017         },
16018         {
16019                 .name  = "LOCAL-SUBSTITUTE",
16020                 .fn    = run_local_substitute,
16021         },
16022         {
16023                 .name  = "LOCAL-GENCACHE",
16024                 .fn    = run_local_gencache,
16025         },
16026         {
16027                 .name  = "LOCAL-DBWRAP-WATCH1",
16028                 .fn    = run_dbwrap_watch1,
16029         },
16030         {
16031                 .name  = "LOCAL-DBWRAP-WATCH2",
16032                 .fn    = run_dbwrap_watch2,
16033         },
16034         {
16035                 .name  = "LOCAL-DBWRAP-WATCH3",
16036                 .fn    = run_dbwrap_watch3,
16037         },
16038         {
16039                 .name  = "LOCAL-DBWRAP-WATCH4",
16040                 .fn    = run_dbwrap_watch4,
16041         },
16042         {
16043                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
16044                 .fn    = run_dbwrap_do_locked1,
16045         },
16046         {
16047                 .name  = "LOCAL-MESSAGING-READ1",
16048                 .fn    = run_messaging_read1,
16049         },
16050         {
16051                 .name  = "LOCAL-MESSAGING-READ2",
16052                 .fn    = run_messaging_read2,
16053         },
16054         {
16055                 .name  = "LOCAL-MESSAGING-READ3",
16056                 .fn    = run_messaging_read3,
16057         },
16058         {
16059                 .name  = "LOCAL-MESSAGING-READ4",
16060                 .fn    = run_messaging_read4,
16061         },
16062         {
16063                 .name  = "LOCAL-MESSAGING-FDPASS1",
16064                 .fn    = run_messaging_fdpass1,
16065         },
16066         {
16067                 .name  = "LOCAL-MESSAGING-FDPASS2",
16068                 .fn    = run_messaging_fdpass2,
16069         },
16070         {
16071                 .name  = "LOCAL-MESSAGING-FDPASS2a",
16072                 .fn    = run_messaging_fdpass2a,
16073         },
16074         {
16075                 .name  = "LOCAL-MESSAGING-FDPASS2b",
16076                 .fn    = run_messaging_fdpass2b,
16077         },
16078         {
16079                 .name  = "LOCAL-MESSAGING-SEND-ALL",
16080                 .fn    = run_messaging_send_all,
16081         },
16082         {
16083                 .name  = "LOCAL-BASE64",
16084                 .fn    = run_local_base64,
16085         },
16086         {
16087                 .name  = "LOCAL-RBTREE",
16088                 .fn    = run_local_rbtree,
16089         },
16090         {
16091                 .name  = "LOCAL-MEMCACHE",
16092                 .fn    = run_local_memcache,
16093         },
16094         {
16095                 .name  = "LOCAL-STREAM-NAME",
16096                 .fn    = run_local_stream_name,
16097         },
16098         {
16099                 .name  = "LOCAL-STR-MATCH-MSWILD",
16100                 .fn    = run_str_match_mswild,
16101         },
16102         {
16103                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
16104                 .fn    = run_str_match_regex_sub1,
16105         },
16106         {
16107                 .name  = "WBCLIENT-MULTI-PING",
16108                 .fn    = run_wbclient_multi_ping,
16109         },
16110         {
16111                 .name  = "LOCAL-string_to_sid",
16112                 .fn    = run_local_string_to_sid,
16113         },
16114         {
16115                 .name  = "LOCAL-sid_to_string",
16116                 .fn    = run_local_sid_to_string,
16117         },
16118         {
16119                 .name  = "LOCAL-binary_to_sid",
16120                 .fn    = run_local_binary_to_sid,
16121         },
16122         {
16123                 .name  = "LOCAL-DBTRANS",
16124                 .fn    = run_local_dbtrans,
16125         },
16126         {
16127                 .name  = "LOCAL-TEVENT-POLL",
16128                 .fn    = run_local_tevent_poll,
16129         },
16130         {
16131                 .name  = "LOCAL-CONVERT-STRING",
16132                 .fn    = run_local_convert_string,
16133         },
16134         {
16135                 .name  = "LOCAL-CONV-AUTH-INFO",
16136                 .fn    = run_local_conv_auth_info,
16137         },
16138         {
16139                 .name  = "LOCAL-hex_encode_buf",
16140                 .fn    = run_local_hex_encode_buf,
16141         },
16142         {
16143                 .name  = "LOCAL-IDMAP-TDB-COMMON",
16144                 .fn    = run_idmap_tdb_common_test,
16145         },
16146         {
16147                 .name  = "LOCAL-remove_duplicate_addrs2",
16148                 .fn    = run_local_remove_duplicate_addrs2,
16149         },
16150         {
16151                 .name  = "local-tdb-opener",
16152                 .fn    = run_local_tdb_opener,
16153         },
16154         {
16155                 .name  = "local-tdb-writer",
16156                 .fn    = run_local_tdb_writer,
16157         },
16158         {
16159                 .name  = "LOCAL-DBWRAP-CTDB1",
16160                 .fn    = run_local_dbwrap_ctdb1,
16161         },
16162         {
16163                 .name  = "LOCAL-BENCH-PTHREADPOOL",
16164                 .fn    = run_bench_pthreadpool,
16165         },
16166         {
16167                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
16168                 .fn    = run_pthreadpool_tevent,
16169         },
16170         {
16171                 .name  = "LOCAL-G-LOCK1",
16172                 .fn    = run_g_lock1,
16173         },
16174         {
16175                 .name  = "LOCAL-G-LOCK2",
16176                 .fn    = run_g_lock2,
16177         },
16178         {
16179                 .name  = "LOCAL-G-LOCK3",
16180                 .fn    = run_g_lock3,
16181         },
16182         {
16183                 .name  = "LOCAL-G-LOCK4",
16184                 .fn    = run_g_lock4,
16185         },
16186         {
16187                 .name  = "LOCAL-G-LOCK4A",
16188                 .fn    = run_g_lock4a,
16189         },
16190         {
16191                 .name  = "LOCAL-G-LOCK5",
16192                 .fn    = run_g_lock5,
16193         },
16194         {
16195                 .name  = "LOCAL-G-LOCK6",
16196                 .fn    = run_g_lock6,
16197         },
16198         {
16199                 .name  = "LOCAL-G-LOCK7",
16200                 .fn    = run_g_lock7,
16201         },
16202         {
16203                 .name  = "LOCAL-G-LOCK8",
16204                 .fn    = run_g_lock8,
16205         },
16206         {
16207                 .name  = "LOCAL-G-LOCK-PING-PONG",
16208                 .fn    = run_g_lock_ping_pong,
16209         },
16210         {
16211                 .name  = "LOCAL-CANONICALIZE-PATH",
16212                 .fn    = run_local_canonicalize_path,
16213         },
16214         {
16215                 .name  = "LOCAL-NAMEMAP-CACHE1",
16216                 .fn    = run_local_namemap_cache1,
16217         },
16218         {
16219                 .name  = "LOCAL-IDMAP-CACHE1",
16220                 .fn    = run_local_idmap_cache1,
16221         },
16222         {
16223                 .name  = "qpathinfo-bufsize",
16224                 .fn    = run_qpathinfo_bufsize,
16225         },
16226         {
16227                 .name  = "hide-new-files-timeout",
16228                 .fn    = run_hidenewfiles,
16229         },
16230         {
16231                 .name  = "hide-new-files-timeout-showdirs",
16232                 .fn    = run_hidenewfiles_showdirs,
16233         },
16234 #ifdef CLUSTER_SUPPORT
16235         {
16236                 .name  = "ctdbd-conn1",
16237                 .fn    = run_ctdbd_conn1,
16238         },
16239 #endif
16240         {
16241                 .name  = "readdir-timestamp",
16242                 .fn    = run_readdir_timestamp,
16243         },
16244         {
16245                 .name  = "rpc-scale",
16246                 .fn    = run_rpc_scale,
16247         },
16248         {
16249                 .name  = "LOCAL-TDB-VALIDATE",
16250                 .fn    = run_tdb_validate,
16251         },
16252         {
16253                 .name = NULL,
16254         },
16255 };
16256
16257 /****************************************************************************
16258 run a specified test or "ALL"
16259 ****************************************************************************/
16260 static bool run_test(const char *name)
16261 {
16262         bool ret = True;
16263         bool result = True;
16264         bool found = False;
16265         int i;
16266         double t;
16267         if (strequal(name,"ALL")) {
16268                 for (i=0;torture_ops[i].name;i++) {
16269                         run_test(torture_ops[i].name);
16270                 }
16271                 found = True;
16272         }
16273
16274         for (i=0;torture_ops[i].name;i++) {
16275                 fstr_sprintf(randomfname, "\\XX%x",
16276                          (unsigned)random());
16277
16278                 if (strequal(name, torture_ops[i].name)) {
16279                         found = True;
16280                         printf("Running %s\n", name);
16281                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
16282                                 t = create_procs(torture_ops[i].fn, &result);
16283                                 if (!result) {
16284                                         ret = False;
16285                                         printf("TEST %s FAILED!\n", name);
16286                                 }
16287                         } else {
16288                                 struct timeval start;
16289                                 start = timeval_current();
16290                                 if (!torture_ops[i].fn(0)) {
16291                                         ret = False;
16292                                         printf("TEST %s FAILED!\n", name);
16293                                 }
16294                                 t = timeval_elapsed(&start);
16295                         }
16296                         printf("%s took %g secs\n\n", name, t);
16297                 }
16298         }
16299
16300         if (!found) {
16301                 printf("Did not find a test named %s\n", name);
16302                 ret = False;
16303         }
16304
16305         return ret;
16306 }
16307
16308
16309 static void usage(void)
16310 {
16311         int i;
16312
16313         printf("WARNING samba4 test suite is much more complete nowadays.\n");
16314         printf("Please use samba4 torture.\n\n");
16315
16316         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16317
16318         printf("\t-d debuglevel\n");
16319         printf("\t-U user%%pass\n");
16320         printf("\t-k                    use kerberos\n");
16321         printf("\t-N numprocs\n");
16322         printf("\t-n my_netbios_name\n");
16323         printf("\t-W workgroup\n");
16324         printf("\t-o num_operations\n");
16325         printf("\t-O socket_options\n");
16326         printf("\t-m maximum protocol\n");
16327         printf("\t-L use oplocks\n");
16328         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
16329         printf("\t-A showall\n");
16330         printf("\t-p port\n");
16331         printf("\t-s seed\n");
16332         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
16333         printf("\t-f filename           filename to test\n");
16334         printf("\t-e                    encrypt\n");
16335         printf("\t-T 'OPTION=VALUE'     smb.conf option line\n");
16336         printf("\n\n");
16337
16338         printf("tests are:");
16339         for (i=0;torture_ops[i].name;i++) {
16340                 printf(" %s", torture_ops[i].name);
16341         }
16342         printf("\n");
16343
16344         printf("default test is ALL\n");
16345
16346         exit(1);
16347 }
16348
16349 /****************************************************************************
16350   main program
16351 ****************************************************************************/
16352  int main(int argc,char *argv[])
16353 {
16354         int opt, i;
16355         char *p;
16356         int gotuser = 0;
16357         int gotpass = 0;
16358         bool correct = True;
16359         TALLOC_CTX *frame = talloc_stackframe();
16360         int seed = time(NULL);
16361         struct loadparm_context *lp_ctx = NULL;
16362
16363 #ifdef HAVE_SETBUFFER
16364         setbuffer(stdout, NULL, 0);
16365 #endif
16366
16367         setup_logging("smbtorture", DEBUG_STDOUT);
16368
16369         smb_init_locale();
16370         fault_setup();
16371
16372         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16373         if (lp_ctx == NULL) {
16374                 fprintf(stderr,
16375                         "Failed to initialise the global parameter structure.\n");
16376                 return 1;
16377         }
16378
16379         if (is_default_dyn_CONFIGFILE()) {
16380                 if(getenv("SMB_CONF_PATH")) {
16381                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16382                 }
16383         }
16384         lp_load_global(get_dyn_CONFIGFILE());
16385         load_interfaces();
16386
16387         if (argc < 2) {
16388                 usage();
16389         }
16390
16391         for(p = argv[1]; *p; p++)
16392           if(*p == '\\')
16393             *p = '/';
16394
16395         if (strncmp(argv[1], "//", 2)) {
16396                 usage();
16397         }
16398
16399         fstrcpy(host, &argv[1][2]);
16400         p = strchr_m(&host[2],'/');
16401         if (!p) {
16402                 usage();
16403         }
16404         *p = 0;
16405         fstrcpy(share, p+1);
16406
16407         fstrcpy(myname, get_myname(talloc_tos()));
16408         if (!*myname) {
16409                 fprintf(stderr, "Failed to get my hostname.\n");
16410                 return 1;
16411         }
16412
16413         if (*username == 0 && getenv("LOGNAME")) {
16414           fstrcpy(username,getenv("LOGNAME"));
16415         }
16416
16417         argc--;
16418         argv++;
16419
16420         fstrcpy(workgroup, lp_workgroup());
16421
16422         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16423                != EOF) {
16424                 switch (opt) {
16425                 case 'p':
16426                         port_to_use = atoi(optarg);
16427                         break;
16428                 case 's':
16429                         seed = atoi(optarg);
16430                         break;
16431                 case 'W':
16432                         fstrcpy(workgroup,optarg);
16433                         break;
16434                 case 'm':
16435                         lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16436                         break;
16437                 case 'N':
16438                         torture_nprocs = atoi(optarg);
16439                         break;
16440                 case 'o':
16441                         torture_numops = atoi(optarg);
16442                         break;
16443                 case 'd':
16444                         lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16445                         break;
16446                 case 'O':
16447                         sockops = optarg;
16448                         break;
16449                 case 'L':
16450                         use_oplocks = True;
16451                         break;
16452                 case 'l':
16453                         local_path = optarg;
16454                         break;
16455                 case 'A':
16456                         torture_showall = True;
16457                         break;
16458                 case 'n':
16459                         fstrcpy(myname, optarg);
16460                         break;
16461                 case 'c':
16462                         client_txt = optarg;
16463                         break;
16464                 case 'e':
16465                         do_encrypt = true;
16466                         break;
16467                 case 'k':
16468 #ifdef HAVE_KRB5
16469                         use_kerberos = True;
16470 #else
16471                         d_printf("No kerberos support compiled in\n");
16472                         exit(1);
16473 #endif
16474                         break;
16475                 case 'U':
16476                         gotuser = 1;
16477                         fstrcpy(username,optarg);
16478                         p = strchr_m(username,'%');
16479                         if (p) {
16480                                 *p = 0;
16481                                 fstrcpy(password, p+1);
16482                                 gotpass = 1;
16483                         }
16484                         break;
16485                 case 'b':
16486                         fstrcpy(multishare_conn_fname, optarg);
16487                         use_multishare_conn = True;
16488                         break;
16489                 case 'B':
16490                         torture_blocksize = atoi(optarg);
16491                         break;
16492                 case 'f':
16493                         test_filename = SMB_STRDUP(optarg);
16494                         break;
16495                 case 'T':
16496                         lpcfg_set_option(lp_ctx, optarg);
16497                         break;
16498                 default:
16499                         printf("Unknown option %c (%d)\n", (char)opt, opt);
16500                         usage();
16501                 }
16502         }
16503
16504         d_printf("using seed %d\n", seed);
16505
16506         srandom(seed);
16507
16508         if(use_kerberos && !gotuser) gotpass = True;
16509
16510         while (!gotpass) {
16511                 char pwd[256] = {0};
16512                 int rc;
16513
16514                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16515                 if (rc == 0) {
16516                         fstrcpy(password, pwd);
16517                         gotpass = 1;
16518                 }
16519         }
16520
16521         printf("host=%s share=%s user=%s myname=%s\n",
16522                host, share, username, myname);
16523
16524         torture_creds = cli_session_creds_init(frame,
16525                                                username,
16526                                                workgroup,
16527                                                NULL, /* realm */
16528                                                password,
16529                                                use_kerberos,
16530                                                false, /* fallback_after_kerberos */
16531                                                false, /* use_ccache */
16532                                                false); /* password_is_nt_hash */
16533         if (torture_creds == NULL) {
16534                 d_printf("cli_session_creds_init() failed.\n");
16535                 exit(1);
16536         }
16537
16538         if (argc == optind) {
16539                 correct = run_test("ALL");
16540         } else {
16541                 for (i=optind;i<argc;i++) {
16542                         if (!run_test(argv[i])) {
16543                                 correct = False;
16544                         }
16545                 }
16546         }
16547
16548         TALLOC_FREE(frame);
16549
16550         if (correct) {
16551                 return(0);
16552         } else {
16553                 return(1);
16554         }
16555 }