s3:libsmb: Pass memory context to cli_connect_nb()
[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(NULL,
161                                 host,
162                                 NULL,
163                                 port_to_use,
164                                 0x20,
165                                 myname,
166                                 signing_state,
167                                 flags,
168                                 &c);
169         if (!NT_STATUS_IS_OK(status)) {
170                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
171                 return NULL;
172         }
173
174         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
175
176         return c;
177 }
178
179 /****************************************************************************
180  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
181 ****************************************************************************/
182
183 static bool cli_bad_session_request(int fd,
184                          struct nmb_name *calling, struct nmb_name *called)
185 {
186         TALLOC_CTX *frame;
187         uint8_t len_buf[4];
188         struct iovec iov[3];
189         ssize_t len;
190         uint8_t *inbuf;
191         int err;
192         bool ret = false;
193         uint8_t message_type;
194         uint8_t error;
195         struct tevent_context *ev;
196         struct tevent_req *req;
197
198         frame = talloc_stackframe();
199
200         iov[0].iov_base = len_buf;
201         iov[0].iov_len  = sizeof(len_buf);
202
203         /* put in the destination name */
204
205         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
206                                       called->name_type);
207         if (iov[1].iov_base == NULL) {
208                 goto fail;
209         }
210         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
211                                   talloc_get_size(iov[1].iov_base));
212
213         /* and my name */
214
215         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
216                                       calling->name_type);
217         if (iov[2].iov_base == NULL) {
218                 goto fail;
219         }
220         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
221                                   talloc_get_size(iov[2].iov_base));
222
223         /* Deliberately corrupt the name len (first byte) */
224         *((uint8_t *)iov[2].iov_base) = 100;
225
226         /* send a session request (RFC 1002) */
227         /* setup the packet length
228          * Remove four bytes from the length count, since the length
229          * field in the NBT Session Service header counts the number
230          * of bytes which follow.  The cli_send_smb() function knows
231          * about this and accounts for those four bytes.
232          * CRH.
233          */
234
235         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
236         SCVAL(len_buf,0,0x81);
237
238         len = write_data_iov(fd, iov, 3);
239         if (len == -1) {
240                 goto fail;
241         }
242
243         ev = samba_tevent_context_init(frame);
244         if (ev == NULL) {
245                 goto fail;
246         }
247         req = read_smb_send(frame, ev, fd);
248         if (req == NULL) {
249                 goto fail;
250         }
251         if (!tevent_req_poll(req, ev)) {
252                 goto fail;
253         }
254         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
255         if (len == -1) {
256                 errno = err;
257                 goto fail;
258         }
259         TALLOC_FREE(ev);
260
261         message_type = CVAL(inbuf, 0);
262         if (message_type != 0x83) {
263                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
264                           message_type);
265                 goto fail;
266         }
267
268         if (smb_len(inbuf) != 1) {
269                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
270                           (int)smb_len(inbuf));
271                 goto fail;
272         }
273
274         error = CVAL(inbuf, 4);
275         if (error !=  0x82) {
276                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
277                           (int)error);
278                 goto fail;
279         }
280
281         ret = true;
282 fail:
283         TALLOC_FREE(frame);
284         return ret;
285 }
286
287 /* Insert a NULL at the first separator of the given path and return a pointer
288  * to the remainder of the string.
289  */
290 static char *
291 terminate_path_at_separator(char * path)
292 {
293         char * p;
294
295         if (!path) {
296                 return NULL;
297         }
298
299         if ((p = strchr_m(path, '/'))) {
300                 *p = '\0';
301                 return p + 1;
302         }
303
304         if ((p = strchr_m(path, '\\'))) {
305                 *p = '\0';
306                 return p + 1;
307         }
308
309         /* No separator. */
310         return NULL;
311 }
312
313 /*
314   parse a //server/share type UNC name
315 */
316 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
317                       char **hostname, char **sharename)
318 {
319         char *p;
320
321         *hostname = *sharename = NULL;
322
323         if (strncmp(unc_name, "\\\\", 2) &&
324             strncmp(unc_name, "//", 2)) {
325                 return False;
326         }
327
328         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
329         p = terminate_path_at_separator(*hostname);
330
331         if (p && *p) {
332                 *sharename = talloc_strdup(mem_ctx, p);
333                 terminate_path_at_separator(*sharename);
334         }
335
336         if (*hostname && *sharename) {
337                 return True;
338         }
339
340         TALLOC_FREE(*hostname);
341         TALLOC_FREE(*sharename);
342         return False;
343 }
344
345 static bool torture_open_connection_share(struct cli_state **c,
346                                    const char *hostname,
347                                    const char *sharename,
348                                    int flags)
349 {
350         NTSTATUS status;
351
352         status = cli_full_connection_creds(c,
353                                            myname,
354                                            hostname,
355                                            NULL, /* dest_ss */
356                                            port_to_use,
357                                            sharename,
358                                            "?????",
359                                            torture_creds,
360                                            flags);
361         if (!NT_STATUS_IS_OK(status)) {
362                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
363                         hostname, sharename, port_to_use, nt_errstr(status));
364                 return False;
365         }
366
367         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
368
369         if (do_encrypt) {
370                 return force_cli_encryption(*c,
371                                         sharename);
372         }
373         return True;
374 }
375
376 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
377 {
378         char **unc_list = NULL;
379         int num_unc_names = 0;
380         bool result;
381
382         if (use_multishare_conn==True) {
383                 char *h, *s;
384                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
385                 if (!unc_list || num_unc_names <= 0) {
386                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
387                         exit(1);
388                 }
389
390                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
391                                       NULL, &h, &s)) {
392                         printf("Failed to parse UNC name %s\n",
393                                unc_list[conn_index % num_unc_names]);
394                         TALLOC_FREE(unc_list);
395                         exit(1);
396                 }
397
398                 result = torture_open_connection_share(c, h, s, flags);
399
400                 /* h, s were copied earlier */
401                 TALLOC_FREE(unc_list);
402                 return result;
403         }
404
405         return torture_open_connection_share(c, host, share, flags);
406 }
407
408 bool torture_open_connection(struct cli_state **c, int conn_index)
409 {
410         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
411
412         if (use_oplocks) {
413                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
414         }
415         if (use_level_II_oplocks) {
416                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
417         }
418
419         return torture_open_connection_flags(c, conn_index, flags);
420 }
421
422 bool torture_init_connection(struct cli_state **pcli)
423 {
424         struct cli_state *cli;
425
426         cli = open_nbt_connection();
427         if (cli == NULL) {
428                 return false;
429         }
430
431         *pcli = cli;
432         return true;
433 }
434
435 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
436 {
437         uint16_t old_vuid = cli_state_get_uid(cli);
438         NTSTATUS status;
439         bool ret;
440
441         cli_state_set_uid(cli, 0);
442         status = cli_session_setup_creds(cli, torture_creds);
443         ret = NT_STATUS_IS_OK(status);
444         *new_vuid = cli_state_get_uid(cli);
445         cli_state_set_uid(cli, old_vuid);
446         return ret;
447 }
448
449
450 bool torture_close_connection(struct cli_state *c)
451 {
452         bool ret = True;
453         NTSTATUS status;
454
455         status = cli_tdis(c);
456         if (!NT_STATUS_IS_OK(status)) {
457                 printf("tdis failed (%s)\n", nt_errstr(status));
458                 ret = False;
459         }
460
461         cli_shutdown(c);
462
463         return ret;
464 }
465
466 void torture_conn_set_sockopt(struct cli_state *cli)
467 {
468         smbXcli_conn_set_sockopt(cli->conn, sockops);
469 }
470
471 static NTSTATUS torture_delete_fn(struct file_info *finfo,
472                                   const char *pattern,
473                                   void *state)
474 {
475         NTSTATUS status;
476         char *filename = NULL;
477         char *dirname = NULL;
478         char *p = NULL;
479         TALLOC_CTX *frame = talloc_stackframe();
480         struct cli_state *cli = (struct cli_state *)state;
481
482         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
483                 TALLOC_FREE(frame);
484                 return NT_STATUS_OK;
485         }
486
487         dirname = talloc_strdup(frame, pattern);
488         if (dirname == NULL) {
489                 TALLOC_FREE(frame);
490                 return NT_STATUS_NO_MEMORY;
491         }
492         p = strrchr_m(dirname, '\\');
493         if (p != NULL) {
494                 /* Remove the terminating '\' */
495                 *p = '\0';
496         }
497         if (dirname[0] != '\0') {
498                 filename = talloc_asprintf(frame,
499                                            "%s\\%s",
500                                            dirname,
501                                            finfo->name);
502         } else {
503                 filename = talloc_asprintf(frame,
504                                            "%s",
505                                            finfo->name);
506         }
507         if (filename == NULL) {
508                 TALLOC_FREE(frame);
509                 return NT_STATUS_NO_MEMORY;
510         }
511         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
512                 char *subdirname = talloc_asprintf(frame,
513                                                    "%s\\*",
514                                                    filename);
515                 if (subdirname == NULL) {
516                         TALLOC_FREE(frame);
517                         return NT_STATUS_NO_MEMORY;
518                 }
519                 status = cli_list(cli,
520                                   subdirname,
521                                   FILE_ATTRIBUTE_DIRECTORY |
522                                           FILE_ATTRIBUTE_HIDDEN |
523                                           FILE_ATTRIBUTE_SYSTEM,
524                                   torture_delete_fn,
525                                   cli);
526                 if (!NT_STATUS_IS_OK(status)) {
527                         printf("torture_delete_fn: cli_list "
528                                 "of %s failed (%s)\n",
529                                 subdirname,
530                                 nt_errstr(status));
531                         TALLOC_FREE(frame);
532                         return status;
533                 }
534                 status = cli_rmdir(cli, filename);
535         } else {
536                 status = cli_unlink(cli,
537                                     filename,
538                                     FILE_ATTRIBUTE_SYSTEM |
539                                         FILE_ATTRIBUTE_HIDDEN);
540         }
541         if (!NT_STATUS_IS_OK(status)) {
542                 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
543                         printf("torture_delete_fn: cli_rmdir"
544                                 " of %s failed (%s)\n",
545                                 filename,
546                                 nt_errstr(status));
547                 } else {
548                         printf("torture_delete_fn: cli_unlink"
549                                 " of %s failed (%s)\n",
550                                 filename,
551                                 nt_errstr(status));
552                 }
553         }
554         TALLOC_FREE(frame);
555         return status;
556 }
557
558 void torture_deltree(struct cli_state *cli, const char *dname)
559 {
560         char *mask = NULL;
561         NTSTATUS status;
562
563         /* It might be a file */
564         (void)cli_unlink(cli,
565                          dname,
566                          FILE_ATTRIBUTE_SYSTEM |
567                                 FILE_ATTRIBUTE_HIDDEN);
568
569         mask = talloc_asprintf(cli,
570                                "%s\\*",
571                                dname);
572         if (mask == NULL) {
573                 printf("torture_deltree: talloc_asprintf failed\n");
574                 return;
575         }
576
577         status = cli_list(cli,
578                         mask,
579                         FILE_ATTRIBUTE_DIRECTORY |
580                                 FILE_ATTRIBUTE_HIDDEN|
581                                 FILE_ATTRIBUTE_SYSTEM,
582                         torture_delete_fn,
583                         cli);
584         if (!NT_STATUS_IS_OK(status)) {
585                 printf("torture_deltree: cli_list of %s failed (%s)\n",
586                         mask,
587                         nt_errstr(status));
588         }
589         TALLOC_FREE(mask);
590         status = cli_rmdir(cli, dname);
591         if (!NT_STATUS_IS_OK(status)) {
592                 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
593                         dname,
594                         nt_errstr(status));
595         }
596 }
597
598 /* check if the server produced the expected dos or nt error code */
599 static bool check_both_error(int line, NTSTATUS status,
600                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
601 {
602         if (NT_STATUS_IS_DOS(status)) {
603                 uint8_t cclass;
604                 uint32_t num;
605
606                 /* Check DOS error */
607                 cclass = NT_STATUS_DOS_CLASS(status);
608                 num = NT_STATUS_DOS_CODE(status);
609
610                 if (eclass != cclass || ecode != num) {
611                         printf("unexpected error code class=%d code=%d\n",
612                                (int)cclass, (int)num);
613                         printf(" expected %d/%d %s (line=%d)\n",
614                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
615                         return false;
616                 }
617         } else {
618                 /* Check NT error */
619                 if (!NT_STATUS_EQUAL(nterr, status)) {
620                         printf("unexpected error code %s\n",
621                                 nt_errstr(status));
622                         printf(" expected %s (line=%d)\n",
623                                 nt_errstr(nterr), line);
624                         return false;
625                 }
626         }
627
628         return true;
629 }
630
631
632 /* check if the server produced the expected error code */
633 static bool check_error(int line, NTSTATUS status,
634                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
635 {
636         if (NT_STATUS_IS_DOS(status)) {
637                 uint8_t cclass;
638                 uint32_t num;
639
640                 /* Check DOS error */
641
642                 cclass = NT_STATUS_DOS_CLASS(status);
643                 num = NT_STATUS_DOS_CODE(status);
644
645                 if (eclass != cclass || ecode != num) {
646                         printf("unexpected error code class=%d code=%d\n",
647                                (int)cclass, (int)num);
648                         printf(" expected %d/%d %s (line=%d)\n",
649                                (int)eclass, (int)ecode, nt_errstr(nterr),
650                                line);
651                         return False;
652                 }
653
654         } else {
655                 /* Check NT error */
656
657                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
658                         printf("unexpected error code %s\n",
659                                nt_errstr(status));
660                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
661                                line);
662                         return False;
663                 }
664         }
665
666         return True;
667 }
668
669 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
670                         const char *fname,
671                         time_t *change_time,
672                         time_t *access_time,
673                         time_t *write_time,
674                         off_t *size,
675                         uint32_t *pattr)
676 {
677         int timezone = smb1cli_conn_server_time_zone(cli->conn);
678         time_t (*date_fn)(const void *buf, int serverzone) = NULL;
679         uint8_t *rdata = NULL;
680         uint32_t num_rdata;
681         NTSTATUS status;
682
683         status = cli_qpathinfo(talloc_tos(),
684                                cli,
685                                fname,
686                                SMB_INFO_STANDARD,
687                                22,
688                                CLI_BUFFER_SIZE,
689                                &rdata,
690                                &num_rdata);
691         if (!NT_STATUS_IS_OK(status)) {
692                 return status;
693         }
694         if (cli->win95) {
695                 date_fn = make_unix_date;
696         } else {
697                 date_fn = make_unix_date2;
698         }
699
700         if (change_time) {
701                 *change_time = date_fn(rdata + 0, timezone);
702         }
703         if (access_time) {
704                 *access_time = date_fn(rdata + 4, timezone);
705         }
706         if (write_time) {
707                 *write_time = date_fn(rdata + 8, timezone);
708         }
709         if (size) {
710                 *size = PULL_LE_U32(rdata, 12);
711         }
712         if (pattr) {
713                 *pattr = PULL_LE_U16(rdata, l1_attrFile);
714         }
715         return NT_STATUS_OK;
716 }
717
718 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
719 {
720         NTSTATUS status;
721
722         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
723
724         while (!NT_STATUS_IS_OK(status)) {
725                 if (!check_both_error(__LINE__, status, ERRDOS,
726                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
727                         return false;
728                 }
729
730                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
731         }
732
733         return true;
734 }
735
736
737 static bool rw_torture(struct cli_state *c)
738 {
739         const char *lockfname = "\\torture.lck";
740         fstring fname;
741         uint16_t fnum;
742         uint16_t fnum2;
743         pid_t pid2, pid = getpid();
744         int i, j;
745         char buf[1024];
746         bool correct = True;
747         size_t nread = 0;
748         NTSTATUS status;
749
750         memset(buf, '\0', sizeof(buf));
751
752         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
753                          DENY_NONE, &fnum2);
754         if (!NT_STATUS_IS_OK(status)) {
755                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
756         }
757         if (!NT_STATUS_IS_OK(status)) {
758                 printf("open of %s failed (%s)\n",
759                        lockfname, nt_errstr(status));
760                 return False;
761         }
762
763         for (i=0;i<torture_numops;i++) {
764                 unsigned n = (unsigned)sys_random()%10;
765
766                 if (i % 10 == 0) {
767                         printf("%d\r", i); fflush(stdout);
768                 }
769                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
770
771                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
772                         return False;
773                 }
774
775                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
776                                   DENY_ALL, &fnum);
777                 if (!NT_STATUS_IS_OK(status)) {
778                         printf("open failed (%s)\n", nt_errstr(status));
779                         correct = False;
780                         break;
781                 }
782
783                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
784                                       sizeof(pid), NULL);
785                 if (!NT_STATUS_IS_OK(status)) {
786                         printf("write failed (%s)\n", nt_errstr(status));
787                         correct = False;
788                 }
789
790                 for (j=0;j<50;j++) {
791                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
792                                               sizeof(pid)+(j*sizeof(buf)),
793                                               sizeof(buf), NULL);
794                         if (!NT_STATUS_IS_OK(status)) {
795                                 printf("write failed (%s)\n",
796                                        nt_errstr(status));
797                                 correct = False;
798                         }
799                 }
800
801                 pid2 = 0;
802
803                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
804                                   &nread);
805                 if (!NT_STATUS_IS_OK(status)) {
806                         printf("read failed (%s)\n", nt_errstr(status));
807                         correct = false;
808                 } else if (nread != sizeof(pid)) {
809                         printf("read/write compare failed: "
810                                "recv %ld req %ld\n", (unsigned long)nread,
811                                (unsigned long)sizeof(pid));
812                         correct = false;
813                 }
814
815                 if (pid2 != pid) {
816                         printf("data corruption!\n");
817                         correct = False;
818                 }
819
820                 status = cli_close(c, fnum);
821                 if (!NT_STATUS_IS_OK(status)) {
822                         printf("close failed (%s)\n", nt_errstr(status));
823                         correct = False;
824                 }
825
826                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
827                 if (!NT_STATUS_IS_OK(status)) {
828                         printf("unlink failed (%s)\n", nt_errstr(status));
829                         correct = False;
830                 }
831
832                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
833                 if (!NT_STATUS_IS_OK(status)) {
834                         printf("unlock failed (%s)\n", nt_errstr(status));
835                         correct = False;
836                 }
837         }
838
839         cli_close(c, fnum2);
840         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
841
842         printf("%d\n", i);
843
844         return correct;
845 }
846
847 static bool run_torture(int dummy)
848 {
849         struct cli_state *cli;
850         bool ret;
851
852         cli = current_cli;
853
854         smbXcli_conn_set_sockopt(cli->conn, sockops);
855
856         ret = rw_torture(cli);
857
858         if (!torture_close_connection(cli)) {
859                 ret = False;
860         }
861
862         return ret;
863 }
864
865 static bool rw_torture3(struct cli_state *c, char *lockfname)
866 {
867         uint16_t fnum = (uint16_t)-1;
868         unsigned int i = 0;
869         char buf[131072];
870         char buf_rd[131072];
871         unsigned count;
872         unsigned countprev = 0;
873         size_t sent = 0;
874         bool correct = True;
875         NTSTATUS status = NT_STATUS_OK;
876
877         srandom(1);
878         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
879         {
880                 SIVAL(buf, i, sys_random());
881         }
882
883         if (procnum == 0)
884         {
885                 status = cli_unlink(
886                         c, lockfname,
887                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
888                 if (!NT_STATUS_IS_OK(status)) {
889                         printf("unlink failed (%s) (normal, this file should "
890                                "not exist)\n", nt_errstr(status));
891                 }
892
893                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
894                                   DENY_NONE, &fnum);
895                 if (!NT_STATUS_IS_OK(status)) {
896                         printf("first open read/write of %s failed (%s)\n",
897                                         lockfname, nt_errstr(status));
898                         return False;
899                 }
900         }
901         else
902         {
903                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
904                 {
905                         status = cli_openx(c, lockfname, O_RDONLY,
906                                          DENY_NONE, &fnum);
907                         if (NT_STATUS_IS_OK(status)) {
908                                 break;
909                         }
910                         smb_msleep(10);
911                 }
912                 if (!NT_STATUS_IS_OK(status)) {
913                         printf("second open read-only of %s failed (%s)\n",
914                                         lockfname, nt_errstr(status));
915                         return False;
916                 }
917         }
918
919         i = 0;
920         for (count = 0; count < sizeof(buf); count += sent)
921         {
922                 if (count >= countprev) {
923                         printf("%d %8d\r", i, count);
924                         fflush(stdout);
925                         i++;
926                         countprev += (sizeof(buf) / 20);
927                 }
928
929                 if (procnum == 0)
930                 {
931                         sent = ((unsigned)sys_random()%(20))+ 1;
932                         if (sent > sizeof(buf) - count)
933                         {
934                                 sent = sizeof(buf) - count;
935                         }
936
937                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
938                                               count, sent, NULL);
939                         if (!NT_STATUS_IS_OK(status)) {
940                                 printf("write failed (%s)\n",
941                                        nt_errstr(status));
942                                 correct = False;
943                         }
944                 }
945                 else
946                 {
947                         status = cli_read(c, fnum, buf_rd+count, count,
948                                           sizeof(buf)-count, &sent);
949                         if(!NT_STATUS_IS_OK(status)) {
950                                 printf("read failed offset:%d size:%ld (%s)\n",
951                                        count, (unsigned long)sizeof(buf)-count,
952                                        nt_errstr(status));
953                                 correct = False;
954                                 sent = 0;
955                         } else if (sent > 0) {
956                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
957                                 {
958                                         printf("read/write compare failed\n");
959                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
960                                         correct = False;
961                                         break;
962                                 }
963                         }
964                 }
965
966         }
967
968         status = cli_close(c, fnum);
969         if (!NT_STATUS_IS_OK(status)) {
970                 printf("close failed (%s)\n", nt_errstr(status));
971                 correct = False;
972         }
973
974         return correct;
975 }
976
977 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
978 {
979         const char *lockfname = "\\torture2.lck";
980         uint16_t fnum1;
981         uint16_t fnum2;
982         int i;
983         char buf[131072];
984         char buf_rd[131072];
985         bool correct = True;
986         size_t bytes_read;
987         NTSTATUS status;
988
989         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
990         if (!NT_STATUS_IS_OK(status)) {
991                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
992         }
993
994         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
995                           DENY_NONE, &fnum1);
996         if (!NT_STATUS_IS_OK(status)) {
997                 printf("first open read/write of %s failed (%s)\n",
998                                 lockfname, nt_errstr(status));
999                 return False;
1000         }
1001
1002         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
1003         if (!NT_STATUS_IS_OK(status)) {
1004                 printf("second open read-only of %s failed (%s)\n",
1005                                 lockfname, nt_errstr(status));
1006                 cli_close(c1, fnum1);
1007                 return False;
1008         }
1009
1010         for (i = 0; i < torture_numops; i++)
1011         {
1012                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1013                 if (i % 10 == 0) {
1014                         printf("%d\r", i); fflush(stdout);
1015                 }
1016
1017                 generate_random_buffer((unsigned char *)buf, buf_size);
1018
1019                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1020                                       buf_size, NULL);
1021                 if (!NT_STATUS_IS_OK(status)) {
1022                         printf("write failed (%s)\n", nt_errstr(status));
1023                         correct = False;
1024                         break;
1025                 }
1026
1027                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1028                 if(!NT_STATUS_IS_OK(status)) {
1029                         printf("read failed (%s)\n", nt_errstr(status));
1030                         correct = false;
1031                         break;
1032                 } else if (bytes_read != buf_size) {
1033                         printf("read failed\n");
1034                         printf("read %ld, expected %ld\n",
1035                                (unsigned long)bytes_read,
1036                                (unsigned long)buf_size);
1037                         correct = False;
1038                         break;
1039                 }
1040
1041                 if (memcmp(buf_rd, buf, buf_size) != 0)
1042                 {
1043                         printf("read/write compare failed\n");
1044                         correct = False;
1045                         break;
1046                 }
1047         }
1048
1049         status = cli_close(c2, fnum2);
1050         if (!NT_STATUS_IS_OK(status)) {
1051                 printf("close failed (%s)\n", nt_errstr(status));
1052                 correct = False;
1053         }
1054
1055         status = cli_close(c1, fnum1);
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 printf("close failed (%s)\n", nt_errstr(status));
1058                 correct = False;
1059         }
1060
1061         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1062         if (!NT_STATUS_IS_OK(status)) {
1063                 printf("unlink failed (%s)\n", nt_errstr(status));
1064                 correct = False;
1065         }
1066
1067         return correct;
1068 }
1069
1070 static bool run_readwritetest(int dummy)
1071 {
1072         struct cli_state *cli1, *cli2;
1073         bool test1, test2 = False;
1074
1075         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1076                 return False;
1077         }
1078         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1079         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1080
1081         printf("starting readwritetest\n");
1082
1083         test1 = rw_torture2(cli1, cli2);
1084         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1085
1086         if (test1) {
1087                 test2 = rw_torture2(cli1, cli1);
1088                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1089         }
1090
1091         if (!torture_close_connection(cli1)) {
1092                 test1 = False;
1093         }
1094
1095         if (!torture_close_connection(cli2)) {
1096                 test2 = False;
1097         }
1098
1099         return (test1 && test2);
1100 }
1101
1102 static bool run_readwritemulti(int dummy)
1103 {
1104         struct cli_state *cli;
1105         bool test;
1106
1107         cli = current_cli;
1108
1109         smbXcli_conn_set_sockopt(cli->conn, sockops);
1110
1111         printf("run_readwritemulti: fname %s\n", randomfname);
1112         test = rw_torture3(cli, randomfname);
1113
1114         if (!torture_close_connection(cli)) {
1115                 test = False;
1116         }
1117
1118         return test;
1119 }
1120
1121 static bool run_readwritelarge_internal(void)
1122 {
1123         static struct cli_state *cli1;
1124         uint16_t fnum1;
1125         const char *lockfname = "\\large.dat";
1126         off_t fsize;
1127         char buf[126*1024];
1128         bool correct = True;
1129         NTSTATUS status;
1130
1131         if (!torture_open_connection(&cli1, 0)) {
1132                 return False;
1133         }
1134         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1135         memset(buf,'\0',sizeof(buf));
1136
1137         printf("starting readwritelarge_internal\n");
1138
1139         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1140
1141         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1142                           DENY_NONE, &fnum1);
1143         if (!NT_STATUS_IS_OK(status)) {
1144                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1145                 return False;
1146         }
1147
1148         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1149
1150         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1151                                      NULL, NULL, NULL);
1152         if (!NT_STATUS_IS_OK(status)) {
1153                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1154                 correct = False;
1155         }
1156
1157         if (fsize == sizeof(buf))
1158                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1159                        (unsigned long)fsize);
1160         else {
1161                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1162                        (unsigned long)fsize);
1163                 correct = False;
1164         }
1165
1166         status = cli_close(cli1, fnum1);
1167         if (!NT_STATUS_IS_OK(status)) {
1168                 printf("close failed (%s)\n", nt_errstr(status));
1169                 correct = False;
1170         }
1171
1172         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1173         if (!NT_STATUS_IS_OK(status)) {
1174                 printf("unlink failed (%s)\n", nt_errstr(status));
1175                 correct = False;
1176         }
1177
1178         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1179                           DENY_NONE, &fnum1);
1180         if (!NT_STATUS_IS_OK(status)) {
1181                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1182                 return False;
1183         }
1184
1185         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1186
1187         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1188                                      NULL, NULL, NULL);
1189         if (!NT_STATUS_IS_OK(status)) {
1190                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1191                 correct = False;
1192         }
1193
1194         if (fsize == sizeof(buf))
1195                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1196                        (unsigned long)fsize);
1197         else {
1198                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1199                        (unsigned long)fsize);
1200                 correct = False;
1201         }
1202
1203         status = cli_close(cli1, fnum1);
1204         if (!NT_STATUS_IS_OK(status)) {
1205                 printf("close failed (%s)\n", nt_errstr(status));
1206                 correct = False;
1207         }
1208
1209         if (!torture_close_connection(cli1)) {
1210                 correct = False;
1211         }
1212         return correct;
1213 }
1214
1215 static bool run_readwritelarge(int dummy)
1216 {
1217         return run_readwritelarge_internal();
1218 }
1219
1220 static bool run_readwritelarge_signtest(int dummy)
1221 {
1222         bool ret;
1223         signing_state = SMB_SIGNING_REQUIRED;
1224         ret = run_readwritelarge_internal();
1225         signing_state = SMB_SIGNING_DEFAULT;
1226         return ret;
1227 }
1228
1229 int line_count = 0;
1230 int nbio_id;
1231
1232 #define ival(s) strtol(s, NULL, 0)
1233
1234 /* run a test that simulates an approximate netbench client load */
1235 static bool run_netbench(int client)
1236 {
1237         struct cli_state *cli;
1238         int i;
1239         char line[1024];
1240         char cname[20];
1241         FILE *f;
1242         const char *params[20];
1243         bool correct = True;
1244
1245         cli = current_cli;
1246
1247         nbio_id = client;
1248
1249         smbXcli_conn_set_sockopt(cli->conn, sockops);
1250
1251         nb_setup(cli);
1252
1253         slprintf(cname,sizeof(cname)-1, "client%d", client);
1254
1255         f = fopen(client_txt, "r");
1256
1257         if (!f) {
1258                 perror(client_txt);
1259                 return False;
1260         }
1261
1262         while (fgets(line, sizeof(line)-1, f)) {
1263                 char *saveptr;
1264                 line_count++;
1265
1266                 line[strlen(line)-1] = 0;
1267
1268                 /* printf("[%d] %s\n", line_count, line); */
1269
1270                 all_string_sub(line,"client1", cname, sizeof(line));
1271
1272                 /* parse the command parameters */
1273                 params[0] = strtok_r(line, " ", &saveptr);
1274                 i = 0;
1275                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1276
1277                 params[i] = "";
1278
1279                 if (i < 2) continue;
1280
1281                 if (!strncmp(params[0],"SMB", 3)) {
1282                         printf("ERROR: You are using a dbench 1 load file\n");
1283                         exit(1);
1284                 }
1285
1286                 if (!strcmp(params[0],"NTCreateX")) {
1287                         nb_createx(params[1], ival(params[2]), ival(params[3]),
1288                                    ival(params[4]));
1289                 } else if (!strcmp(params[0],"Close")) {
1290                         nb_close(ival(params[1]));
1291                 } else if (!strcmp(params[0],"Rename")) {
1292                         nb_rename(params[1], params[2]);
1293                 } else if (!strcmp(params[0],"Unlink")) {
1294                         nb_unlink(params[1]);
1295                 } else if (!strcmp(params[0],"Deltree")) {
1296                         nb_deltree(params[1]);
1297                 } else if (!strcmp(params[0],"Rmdir")) {
1298                         nb_rmdir(params[1]);
1299                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1300                         nb_qpathinfo(params[1]);
1301                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1302                         nb_qfileinfo(ival(params[1]));
1303                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1304                         nb_qfsinfo(ival(params[1]));
1305                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1306                         nb_findfirst(params[1]);
1307                 } else if (!strcmp(params[0],"WriteX")) {
1308                         nb_writex(ival(params[1]),
1309                                   ival(params[2]), ival(params[3]), ival(params[4]));
1310                 } else if (!strcmp(params[0],"ReadX")) {
1311                         nb_readx(ival(params[1]),
1312                                   ival(params[2]), ival(params[3]), ival(params[4]));
1313                 } else if (!strcmp(params[0],"Flush")) {
1314                         nb_flush(ival(params[1]));
1315                 } else {
1316                         printf("Unknown operation %s\n", params[0]);
1317                         exit(1);
1318                 }
1319         }
1320         fclose(f);
1321
1322         nb_cleanup();
1323
1324         if (!torture_close_connection(cli)) {
1325                 correct = False;
1326         }
1327
1328         return correct;
1329 }
1330
1331
1332 /* run a test that simulates an approximate netbench client load */
1333 static bool run_nbench(int dummy)
1334 {
1335         double t;
1336         bool correct = True;
1337
1338         nbio_shmem(torture_nprocs);
1339
1340         nbio_id = -1;
1341
1342         signal(SIGALRM, nb_alarm);
1343         alarm(1);
1344         t = create_procs(run_netbench, &correct);
1345         alarm(0);
1346
1347         printf("\nThroughput %g MB/sec\n",
1348                1.0e-6 * nbio_total() / t);
1349         return correct;
1350 }
1351
1352
1353 /*
1354   This test checks for two things:
1355
1356   1) correct support for retaining locks over a close (ie. the server
1357      must not use posix semantics)
1358   2) support for lock timeouts
1359  */
1360 static bool run_locktest1(int dummy)
1361 {
1362         struct cli_state *cli1, *cli2;
1363         const char *fname = "\\lockt1.lck";
1364         uint16_t fnum1, fnum2, fnum3;
1365         time_t t1, t2;
1366         unsigned lock_timeout;
1367         NTSTATUS status;
1368
1369         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1370                 return False;
1371         }
1372         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1373         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1374
1375         printf("starting locktest1\n");
1376
1377         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1378
1379         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1380                           &fnum1);
1381         if (!NT_STATUS_IS_OK(status)) {
1382                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1383                 return False;
1384         }
1385
1386         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1387         if (!NT_STATUS_IS_OK(status)) {
1388                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1389                 return False;
1390         }
1391
1392         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1393         if (!NT_STATUS_IS_OK(status)) {
1394                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1395                 return False;
1396         }
1397
1398         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1399         if (!NT_STATUS_IS_OK(status)) {
1400                 printf("lock1 failed (%s)\n", nt_errstr(status));
1401                 return false;
1402         }
1403
1404         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1405         if (NT_STATUS_IS_OK(status)) {
1406                 printf("lock2 succeeded! This is a locking bug\n");
1407                 return false;
1408         } else {
1409                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1410                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1411                         return false;
1412                 }
1413         }
1414
1415         lock_timeout = (1 + (random() % 20));
1416         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1417         t1 = time(NULL);
1418         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1419         if (NT_STATUS_IS_OK(status)) {
1420                 printf("lock3 succeeded! This is a locking bug\n");
1421                 return false;
1422         } else {
1423                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1424                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1425                         return false;
1426                 }
1427         }
1428         t2 = time(NULL);
1429
1430         if (ABS(t2 - t1) < lock_timeout-1) {
1431                 printf("error: This server appears not to support timed lock requests\n");
1432         }
1433
1434         printf("server slept for %u seconds for a %u second timeout\n",
1435                (unsigned int)(t2-t1), lock_timeout);
1436
1437         status = cli_close(cli1, fnum2);
1438         if (!NT_STATUS_IS_OK(status)) {
1439                 printf("close1 failed (%s)\n", nt_errstr(status));
1440                 return False;
1441         }
1442
1443         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1444         if (NT_STATUS_IS_OK(status)) {
1445                 printf("lock4 succeeded! This is a locking bug\n");
1446                 return false;
1447         } else {
1448                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1449                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1450                         return false;
1451                 }
1452         }
1453
1454         status = cli_close(cli1, fnum1);
1455         if (!NT_STATUS_IS_OK(status)) {
1456                 printf("close2 failed (%s)\n", nt_errstr(status));
1457                 return False;
1458         }
1459
1460         status = cli_close(cli2, fnum3);
1461         if (!NT_STATUS_IS_OK(status)) {
1462                 printf("close3 failed (%s)\n", nt_errstr(status));
1463                 return False;
1464         }
1465
1466         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1467         if (!NT_STATUS_IS_OK(status)) {
1468                 printf("unlink failed (%s)\n", nt_errstr(status));
1469                 return False;
1470         }
1471
1472
1473         if (!torture_close_connection(cli1)) {
1474                 return False;
1475         }
1476
1477         if (!torture_close_connection(cli2)) {
1478                 return False;
1479         }
1480
1481         printf("Passed locktest1\n");
1482         return True;
1483 }
1484
1485 /*
1486   this checks to see if a secondary tconx can use open files from an
1487   earlier tconx
1488  */
1489 static bool run_tcon_test(int dummy)
1490 {
1491         static struct cli_state *cli;
1492         const char *fname = "\\tcontest.tmp";
1493         uint16_t fnum1;
1494         uint32_t cnum1, cnum2, cnum3;
1495         struct smbXcli_tcon *orig_tcon = NULL;
1496         char *orig_share = NULL;
1497         uint16_t vuid1, vuid2;
1498         char buf[4];
1499         bool ret = True;
1500         NTSTATUS status;
1501
1502         memset(buf, '\0', sizeof(buf));
1503
1504         if (!torture_open_connection(&cli, 0)) {
1505                 return False;
1506         }
1507         smbXcli_conn_set_sockopt(cli->conn, sockops);
1508
1509         printf("starting tcontest\n");
1510
1511         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1512
1513         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1514         if (!NT_STATUS_IS_OK(status)) {
1515                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1516                 return False;
1517         }
1518
1519         cnum1 = cli_state_get_tid(cli);
1520         vuid1 = cli_state_get_uid(cli);
1521
1522         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1523         if (!NT_STATUS_IS_OK(status)) {
1524                 printf("initial write failed (%s)", nt_errstr(status));
1525                 return False;
1526         }
1527
1528         cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1529
1530         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1531         if (!NT_STATUS_IS_OK(status)) {
1532                 printf("%s refused 2nd tree connect (%s)\n", host,
1533                        nt_errstr(status));
1534                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1535                 cli_shutdown(cli);
1536                 return False;
1537         }
1538
1539         cnum2 = cli_state_get_tid(cli);
1540         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1541         vuid2 = cli_state_get_uid(cli) + 1;
1542
1543         /* try a write with the wrong tid */
1544         cli_state_set_tid(cli, cnum2);
1545
1546         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1547         if (NT_STATUS_IS_OK(status)) {
1548                 printf("* server allows write with wrong TID\n");
1549                 ret = False;
1550         } else {
1551                 printf("server fails write with wrong TID : %s\n",
1552                        nt_errstr(status));
1553         }
1554
1555
1556         /* try a write with an invalid tid */
1557         cli_state_set_tid(cli, cnum3);
1558
1559         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1560         if (NT_STATUS_IS_OK(status)) {
1561                 printf("* server allows write with invalid TID\n");
1562                 ret = False;
1563         } else {
1564                 printf("server fails write with invalid TID : %s\n",
1565                        nt_errstr(status));
1566         }
1567
1568         /* try a write with an invalid vuid */
1569         cli_state_set_uid(cli, vuid2);
1570         cli_state_set_tid(cli, cnum1);
1571
1572         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1573         if (NT_STATUS_IS_OK(status)) {
1574                 printf("* server allows write with invalid VUID\n");
1575                 ret = False;
1576         } else {
1577                 printf("server fails write with invalid VUID : %s\n",
1578                        nt_errstr(status));
1579         }
1580
1581         cli_state_set_tid(cli, cnum1);
1582         cli_state_set_uid(cli, vuid1);
1583
1584         status = cli_close(cli, fnum1);
1585         if (!NT_STATUS_IS_OK(status)) {
1586                 printf("close failed (%s)\n", nt_errstr(status));
1587                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1588                 cli_shutdown(cli);
1589                 return False;
1590         }
1591
1592         cli_state_set_tid(cli, cnum2);
1593
1594         status = cli_tdis(cli);
1595         if (!NT_STATUS_IS_OK(status)) {
1596                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1597                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1598                 cli_shutdown(cli);
1599                 return False;
1600         }
1601
1602         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1603
1604         cli_state_set_tid(cli, cnum1);
1605
1606         if (!torture_close_connection(cli)) {
1607                 return False;
1608         }
1609
1610         return ret;
1611 }
1612
1613
1614 /*
1615  checks for old style tcon support
1616  */
1617 static bool run_tcon2_test(int dummy)
1618 {
1619         static struct cli_state *cli;
1620         uint16_t cnum, max_xmit;
1621         char *service;
1622         NTSTATUS status;
1623
1624         if (!torture_open_connection(&cli, 0)) {
1625                 return False;
1626         }
1627         smbXcli_conn_set_sockopt(cli->conn, sockops);
1628
1629         printf("starting tcon2 test\n");
1630
1631         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1632                 return false;
1633         }
1634
1635         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1636
1637         SAFE_FREE(service);
1638
1639         if (!NT_STATUS_IS_OK(status)) {
1640                 printf("tcon2 failed : %s\n", nt_errstr(status));
1641         } else {
1642                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1643                        (int)max_xmit, (int)cnum);
1644         }
1645
1646         if (!torture_close_connection(cli)) {
1647                 return False;
1648         }
1649
1650         printf("Passed tcon2 test\n");
1651         return True;
1652 }
1653
1654 static bool tcon_devtest(struct cli_state *cli,
1655                          const char *myshare, const char *devtype,
1656                          const char *return_devtype,
1657                          NTSTATUS expected_error)
1658 {
1659         NTSTATUS status;
1660         bool ret;
1661
1662         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1663
1664         if (NT_STATUS_IS_OK(expected_error)) {
1665                 if (NT_STATUS_IS_OK(status)) {
1666                         if (return_devtype != NULL &&
1667                             strequal(cli->dev, return_devtype)) {
1668                                 ret = True;
1669                         } else {
1670                                 printf("tconX to share %s with type %s "
1671                                        "succeeded but returned the wrong "
1672                                        "device type (got [%s] but should have got [%s])\n",
1673                                        myshare, devtype, cli->dev, return_devtype);
1674                                 ret = False;
1675                         }
1676                 } else {
1677                         printf("tconX to share %s with type %s "
1678                                "should have succeeded but failed\n",
1679                                myshare, devtype);
1680                         ret = False;
1681                 }
1682                 cli_tdis(cli);
1683         } else {
1684                 if (NT_STATUS_IS_OK(status)) {
1685                         printf("tconx to share %s with type %s "
1686                                "should have failed but succeeded\n",
1687                                myshare, devtype);
1688                         ret = False;
1689                 } else {
1690                         if (NT_STATUS_EQUAL(status, expected_error)) {
1691                                 ret = True;
1692                         } else {
1693                                 printf("Returned unexpected error\n");
1694                                 ret = False;
1695                         }
1696                 }
1697         }
1698         return ret;
1699 }
1700
1701 /*
1702  checks for correct tconX support
1703  */
1704 static bool run_tcon_devtype_test(int dummy)
1705 {
1706         static struct cli_state *cli1 = NULL;
1707         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1708         NTSTATUS status;
1709         bool ret = True;
1710
1711         status = cli_full_connection_creds(&cli1,
1712                                            myname,
1713                                            host,
1714                                            NULL, /* dest_ss */
1715                                            port_to_use,
1716                                            NULL, /* service */
1717                                            NULL, /* service_type */
1718                                            torture_creds,
1719                                            flags);
1720
1721         if (!NT_STATUS_IS_OK(status)) {
1722                 printf("could not open connection\n");
1723                 return False;
1724         }
1725
1726         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1727                 ret = False;
1728
1729         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1730                 ret = False;
1731
1732         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1733                 ret = False;
1734
1735         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1736                 ret = False;
1737
1738         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1739                 ret = False;
1740
1741         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1742                 ret = False;
1743
1744         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1745                 ret = False;
1746
1747         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1748                 ret = False;
1749
1750         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1751                 ret = False;
1752
1753         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1754                 ret = False;
1755
1756         cli_shutdown(cli1);
1757
1758         if (ret)
1759                 printf("Passed tcondevtest\n");
1760
1761         return ret;
1762 }
1763
1764
1765 /*
1766   This test checks that
1767
1768   1) the server supports multiple locking contexts on the one SMB
1769   connection, distinguished by PID.
1770
1771   2) the server correctly fails overlapping locks made by the same PID (this
1772      goes against POSIX behaviour, which is why it is tricky to implement)
1773
1774   3) the server denies unlock requests by an incorrect client PID
1775 */
1776 static bool run_locktest2(int dummy)
1777 {
1778         static struct cli_state *cli;
1779         const char *fname = "\\lockt2.lck";
1780         uint16_t fnum1, fnum2, fnum3;
1781         bool correct = True;
1782         NTSTATUS status;
1783
1784         if (!torture_open_connection(&cli, 0)) {
1785                 return False;
1786         }
1787
1788         smbXcli_conn_set_sockopt(cli->conn, sockops);
1789
1790         printf("starting locktest2\n");
1791
1792         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1793
1794         cli_setpid(cli, 1);
1795
1796         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1797         if (!NT_STATUS_IS_OK(status)) {
1798                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1799                 return False;
1800         }
1801
1802         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1803         if (!NT_STATUS_IS_OK(status)) {
1804                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1805                 return False;
1806         }
1807
1808         cli_setpid(cli, 2);
1809
1810         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1811         if (!NT_STATUS_IS_OK(status)) {
1812                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1813                 return False;
1814         }
1815
1816         cli_setpid(cli, 1);
1817
1818         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1819         if (!NT_STATUS_IS_OK(status)) {
1820                 printf("lock1 failed (%s)\n", nt_errstr(status));
1821                 return false;
1822         }
1823
1824         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1825         if (NT_STATUS_IS_OK(status)) {
1826                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1827                 correct = false;
1828         } else {
1829                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1830                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1831                         return false;
1832                 }
1833         }
1834
1835         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1836         if (NT_STATUS_IS_OK(status)) {
1837                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1838                 correct = false;
1839         } else {
1840                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1841                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1842                         return false;
1843                 }
1844         }
1845
1846         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1847         if (NT_STATUS_IS_OK(status)) {
1848                 printf("READ lock2 succeeded! This is a locking bug\n");
1849                 correct = false;
1850         } else {
1851                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1852                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1853                         return false;
1854                 }
1855         }
1856
1857         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1858         if (!NT_STATUS_IS_OK(status)) {
1859                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1860         }
1861         cli_setpid(cli, 2);
1862         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1863                 printf("unlock at 100 succeeded! This is a locking bug\n");
1864                 correct = False;
1865         }
1866
1867         status = cli_unlock(cli, fnum1, 0, 4);
1868         if (NT_STATUS_IS_OK(status)) {
1869                 printf("unlock1 succeeded! This is a locking bug\n");
1870                 correct = false;
1871         } else {
1872                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1873                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1874                         return false;
1875                 }
1876         }
1877
1878         status = cli_unlock(cli, fnum1, 0, 8);
1879         if (NT_STATUS_IS_OK(status)) {
1880                 printf("unlock2 succeeded! This is a locking bug\n");
1881                 correct = false;
1882         } else {
1883                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1884                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1885                         return false;
1886                 }
1887         }
1888
1889         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1890         if (NT_STATUS_IS_OK(status)) {
1891                 printf("lock3 succeeded! This is a locking bug\n");
1892                 correct = false;
1893         } else {
1894                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1895                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1896                         return false;
1897                 }
1898         }
1899
1900         cli_setpid(cli, 1);
1901
1902         status = cli_close(cli, fnum1);
1903         if (!NT_STATUS_IS_OK(status)) {
1904                 printf("close1 failed (%s)\n", nt_errstr(status));
1905                 return False;
1906         }
1907
1908         status = cli_close(cli, fnum2);
1909         if (!NT_STATUS_IS_OK(status)) {
1910                 printf("close2 failed (%s)\n", nt_errstr(status));
1911                 return False;
1912         }
1913
1914         status = cli_close(cli, fnum3);
1915         if (!NT_STATUS_IS_OK(status)) {
1916                 printf("close3 failed (%s)\n", nt_errstr(status));
1917                 return False;
1918         }
1919
1920         if (!torture_close_connection(cli)) {
1921                 correct = False;
1922         }
1923
1924         printf("locktest2 finished\n");
1925
1926         return correct;
1927 }
1928
1929
1930 /*
1931   This test checks that
1932
1933   1) the server supports the full offset range in lock requests
1934 */
1935 static bool run_locktest3(int dummy)
1936 {
1937         static struct cli_state *cli1, *cli2;
1938         const char *fname = "\\lockt3.lck";
1939         uint16_t fnum1, fnum2;
1940         int i;
1941         uint32_t offset;
1942         bool correct = True;
1943         NTSTATUS status;
1944
1945 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1946
1947         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1948                 return False;
1949         }
1950         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1951         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1952
1953         printf("starting locktest3\n");
1954
1955         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1956
1957         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1958                          &fnum1);
1959         if (!NT_STATUS_IS_OK(status)) {
1960                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1961                 return False;
1962         }
1963
1964         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1965         if (!NT_STATUS_IS_OK(status)) {
1966                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1967                 return False;
1968         }
1969
1970         for (offset=i=0;i<torture_numops;i++) {
1971                 NEXT_OFFSET;
1972
1973                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1974                 if (!NT_STATUS_IS_OK(status)) {
1975                         printf("lock1 %d failed (%s)\n",
1976                                i,
1977                                nt_errstr(status));
1978                         return False;
1979                 }
1980
1981                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1982                 if (!NT_STATUS_IS_OK(status)) {
1983                         printf("lock2 %d failed (%s)\n",
1984                                i,
1985                                nt_errstr(status));
1986                         return False;
1987                 }
1988         }
1989
1990         for (offset=i=0;i<torture_numops;i++) {
1991                 NEXT_OFFSET;
1992
1993                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1994                 if (NT_STATUS_IS_OK(status)) {
1995                         printf("error: lock1 %d succeeded!\n", i);
1996                         return False;
1997                 }
1998
1999                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
2000                 if (NT_STATUS_IS_OK(status)) {
2001                         printf("error: lock2 %d succeeded!\n", i);
2002                         return False;
2003                 }
2004
2005                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
2006                 if (NT_STATUS_IS_OK(status)) {
2007                         printf("error: lock3 %d succeeded!\n", i);
2008                         return False;
2009                 }
2010
2011                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2012                 if (NT_STATUS_IS_OK(status)) {
2013                         printf("error: lock4 %d succeeded!\n", i);
2014                         return False;
2015                 }
2016         }
2017
2018         for (offset=i=0;i<torture_numops;i++) {
2019                 NEXT_OFFSET;
2020
2021                 status = cli_unlock(cli1, fnum1, offset-1, 1);
2022                 if (!NT_STATUS_IS_OK(status)) {
2023                         printf("unlock1 %d failed (%s)\n",
2024                                i,
2025                                nt_errstr(status));
2026                         return False;
2027                 }
2028
2029                 status = cli_unlock(cli2, fnum2, offset-2, 1);
2030                 if (!NT_STATUS_IS_OK(status)) {
2031                         printf("unlock2 %d failed (%s)\n",
2032                                i,
2033                                nt_errstr(status));
2034                         return False;
2035                 }
2036         }
2037
2038         status = cli_close(cli1, fnum1);
2039         if (!NT_STATUS_IS_OK(status)) {
2040                 printf("close1 failed (%s)\n", nt_errstr(status));
2041                 return False;
2042         }
2043
2044         status = cli_close(cli2, fnum2);
2045         if (!NT_STATUS_IS_OK(status)) {
2046                 printf("close2 failed (%s)\n", nt_errstr(status));
2047                 return False;
2048         }
2049
2050         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2051         if (!NT_STATUS_IS_OK(status)) {
2052                 printf("unlink failed (%s)\n", nt_errstr(status));
2053                 return False;
2054         }
2055
2056         if (!torture_close_connection(cli1)) {
2057                 correct = False;
2058         }
2059
2060         if (!torture_close_connection(cli2)) {
2061                 correct = False;
2062         }
2063
2064         printf("finished locktest3\n");
2065
2066         return correct;
2067 }
2068
2069 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2070                            char *buf, off_t offset, size_t size,
2071                            size_t *nread, size_t expect)
2072 {
2073         NTSTATUS status;
2074         size_t l_nread;
2075
2076         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2077
2078         if(!NT_STATUS_IS_OK(status)) {
2079                 return false;
2080         } else if (l_nread != expect) {
2081                 return false;
2082         }
2083
2084         if (nread) {
2085                 *nread = l_nread;
2086         }
2087
2088         return true;
2089 }
2090
2091 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2092         printf("** "); correct = False; \
2093         }
2094
2095 /*
2096   looks at overlapping locks
2097 */
2098 static bool run_locktest4(int dummy)
2099 {
2100         static struct cli_state *cli1, *cli2;
2101         const char *fname = "\\lockt4.lck";
2102         uint16_t fnum1, fnum2, f;
2103         bool ret;
2104         char buf[1000];
2105         bool correct = True;
2106         NTSTATUS status;
2107
2108         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2109                 return False;
2110         }
2111
2112         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2113         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2114
2115         printf("starting locktest4\n");
2116
2117         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2118
2119         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2120         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2121
2122         memset(buf, 0, sizeof(buf));
2123
2124         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2125                               NULL);
2126         if (!NT_STATUS_IS_OK(status)) {
2127                 printf("Failed to create file: %s\n", nt_errstr(status));
2128                 correct = False;
2129                 goto fail;
2130         }
2131
2132         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2133               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2134         EXPECTED(ret, False);
2135         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2136
2137         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2138               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2139         EXPECTED(ret, True);
2140         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2141
2142         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2143               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2144         EXPECTED(ret, False);
2145         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2146
2147         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2148               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2149         EXPECTED(ret, True);
2150         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2151
2152         ret = (cli_setpid(cli1, 1),
2153               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2154               (cli_setpid(cli1, 2),
2155               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2156         EXPECTED(ret, False);
2157         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2158
2159         ret = (cli_setpid(cli1, 1),
2160               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2161               (cli_setpid(cli1, 2),
2162               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2163         EXPECTED(ret, True);
2164         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2165
2166         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2167               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2168         EXPECTED(ret, True);
2169         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2170
2171         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2172               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2173         EXPECTED(ret, False);
2174         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2175
2176         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2177               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2178         EXPECTED(ret, False);
2179         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2180
2181         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2182               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2183         EXPECTED(ret, True);
2184         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2185
2186         ret = (cli_setpid(cli1, 1),
2187              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2188              (cli_setpid(cli1, 2),
2189              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2190         EXPECTED(ret, False);
2191         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2192
2193         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2194               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2195               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2196         EXPECTED(ret, False);
2197         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2198
2199
2200         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2201               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2202         EXPECTED(ret, False);
2203         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2204
2205         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2206         ret = NT_STATUS_IS_OK(status);
2207         if (ret) {
2208                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2209                                       NULL);
2210                 ret = NT_STATUS_IS_OK(status);
2211         }
2212         EXPECTED(ret, False);
2213         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2214
2215
2216         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2217               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2218               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2219               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2220         EXPECTED(ret, True);
2221         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2222
2223
2224         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2225               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2226               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2227               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2228               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2229                                              150, 4, NULL))) &&
2230               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2231         EXPECTED(ret, True);
2232         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2233
2234         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2235               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2236               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2237                                            160, 4, NULL)) &&
2238               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2239         EXPECTED(ret, True);
2240         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2241
2242         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2243               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2244               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2245                                            170, 4, NULL)) &&
2246               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2247         EXPECTED(ret, True);
2248         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2249
2250         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2251               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2252               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2253               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2254                                             190, 4, NULL)) &&
2255               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2256         EXPECTED(ret, True);
2257         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2258
2259         cli_close(cli1, fnum1);
2260         cli_close(cli2, fnum2);
2261         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2262         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2263         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2264               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2265               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2266               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2267               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2268         cli_close(cli1, f);
2269         cli_close(cli1, fnum1);
2270         EXPECTED(ret, True);
2271         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2272
2273  fail:
2274         cli_close(cli1, fnum1);
2275         cli_close(cli2, fnum2);
2276         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2277         torture_close_connection(cli1);
2278         torture_close_connection(cli2);
2279
2280         printf("finished locktest4\n");
2281         return correct;
2282 }
2283
2284 /*
2285   looks at lock upgrade/downgrade.
2286 */
2287 static bool run_locktest5(int dummy)
2288 {
2289         static struct cli_state *cli1, *cli2;
2290         const char *fname = "\\lockt5.lck";
2291         uint16_t fnum1, fnum2, fnum3;
2292         bool ret;
2293         char buf[1000];
2294         bool correct = True;
2295         NTSTATUS status;
2296
2297         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2298                 return False;
2299         }
2300
2301         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2302         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2303
2304         printf("starting locktest5\n");
2305
2306         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2307
2308         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2309         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2310         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2311
2312         memset(buf, 0, sizeof(buf));
2313
2314         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2315                               NULL);
2316         if (!NT_STATUS_IS_OK(status)) {
2317                 printf("Failed to create file: %s\n", nt_errstr(status));
2318                 correct = False;
2319                 goto fail;
2320         }
2321
2322         /* Check for NT bug... */
2323         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2324               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2325         cli_close(cli1, fnum1);
2326         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2327         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2328         ret = NT_STATUS_IS_OK(status);
2329         EXPECTED(ret, True);
2330         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2331         cli_close(cli1, fnum1);
2332         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2333         cli_unlock(cli1, fnum3, 0, 1);
2334
2335         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2336               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2337         EXPECTED(ret, True);
2338         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2339
2340         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2341         ret = NT_STATUS_IS_OK(status);
2342         EXPECTED(ret, False);
2343
2344         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2345
2346         /* Unlock the process 2 lock. */
2347         cli_unlock(cli2, fnum2, 0, 4);
2348
2349         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2350         ret = NT_STATUS_IS_OK(status);
2351         EXPECTED(ret, False);
2352
2353         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2354
2355         /* Unlock the process 1 fnum3 lock. */
2356         cli_unlock(cli1, fnum3, 0, 4);
2357
2358         /* Stack 2 more locks here. */
2359         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2360               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2361
2362         EXPECTED(ret, True);
2363         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2364
2365         /* Unlock the first process lock, then check this was the WRITE lock that was
2366                 removed. */
2367
2368         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2369               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2370
2371         EXPECTED(ret, True);
2372         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2373
2374         /* Unlock the process 2 lock. */
2375         cli_unlock(cli2, fnum2, 0, 4);
2376
2377         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2378
2379         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2380                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2381                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2382
2383         EXPECTED(ret, True);
2384         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2385
2386         /* Ensure the next unlock fails. */
2387         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2388         EXPECTED(ret, False);
2389         printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2390
2391         /* Ensure connection 2 can get a write lock. */
2392         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2393         ret = NT_STATUS_IS_OK(status);
2394         EXPECTED(ret, True);
2395
2396         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2397
2398
2399  fail:
2400         cli_close(cli1, fnum1);
2401         cli_close(cli2, fnum2);
2402         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2403         if (!torture_close_connection(cli1)) {
2404                 correct = False;
2405         }
2406         if (!torture_close_connection(cli2)) {
2407                 correct = False;
2408         }
2409
2410         printf("finished locktest5\n");
2411
2412         return correct;
2413 }
2414
2415 /*
2416   tries the unusual lockingX locktype bits
2417 */
2418 static bool run_locktest6(int dummy)
2419 {
2420         static struct cli_state *cli;
2421         const char *fname[1] = { "\\lock6.txt" };
2422         int i;
2423         uint16_t fnum;
2424         NTSTATUS status;
2425
2426         if (!torture_open_connection(&cli, 0)) {
2427                 return False;
2428         }
2429
2430         smbXcli_conn_set_sockopt(cli->conn, sockops);
2431
2432         printf("starting locktest6\n");
2433
2434         for (i=0;i<1;i++) {
2435                 printf("Testing %s\n", fname[i]);
2436
2437                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2438
2439                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2440                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2441                 cli_close(cli, fnum);
2442                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2443
2444                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2445                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2446                 cli_close(cli, fnum);
2447                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2448
2449                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2450         }
2451
2452         torture_close_connection(cli);
2453
2454         printf("finished locktest6\n");
2455         return True;
2456 }
2457
2458 static bool run_locktest7(int dummy)
2459 {
2460         struct cli_state *cli1;
2461         const char *fname = "\\lockt7.lck";
2462         uint16_t fnum1;
2463         char buf[200];
2464         bool correct = False;
2465         size_t nread;
2466         NTSTATUS status;
2467
2468         if (!torture_open_connection(&cli1, 0)) {
2469                 return False;
2470         }
2471
2472         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2473
2474         printf("starting locktest7\n");
2475
2476         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2477
2478         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2479
2480         memset(buf, 0, sizeof(buf));
2481
2482         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2483                               NULL);
2484         if (!NT_STATUS_IS_OK(status)) {
2485                 printf("Failed to create file: %s\n", nt_errstr(status));
2486                 goto fail;
2487         }
2488
2489         cli_setpid(cli1, 1);
2490
2491         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 printf("Unable to apply read lock on range 130:4, "
2494                        "error was %s\n", nt_errstr(status));
2495                 goto fail;
2496         } else {
2497                 printf("pid1 successfully locked range 130:4 for READ\n");
2498         }
2499
2500         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2501         if (!NT_STATUS_IS_OK(status)) {
2502                 printf("pid1 unable to read the range 130:4, error was %s\n",
2503                       nt_errstr(status));
2504                 goto fail;
2505         } else if (nread != 4) {
2506                 printf("pid1 unable to read the range 130:4, "
2507                        "recv %ld req %d\n", (unsigned long)nread, 4);
2508                 goto fail;
2509         } else {
2510                 printf("pid1 successfully read the range 130:4\n");
2511         }
2512
2513         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2514         if (!NT_STATUS_IS_OK(status)) {
2515                 printf("pid1 unable to write to the range 130:4, error was "
2516                        "%s\n", nt_errstr(status));
2517                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2518                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2519                         goto fail;
2520                 }
2521         } else {
2522                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2523                 goto fail;
2524         }
2525
2526         cli_setpid(cli1, 2);
2527
2528         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2529         if (!NT_STATUS_IS_OK(status)) {
2530                 printf("pid2 unable to read the range 130:4, error was %s\n",
2531                       nt_errstr(status));
2532                 goto fail;
2533         } else if (nread != 4) {
2534                 printf("pid2 unable to read the range 130:4, "
2535                        "recv %ld req %d\n", (unsigned long)nread, 4);
2536                 goto fail;
2537         } else {
2538                 printf("pid2 successfully read the range 130:4\n");
2539         }
2540
2541         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2542         if (!NT_STATUS_IS_OK(status)) {
2543                 printf("pid2 unable to write to the range 130:4, error was "
2544                        "%s\n", nt_errstr(status));
2545                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2546                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2547                         goto fail;
2548                 }
2549         } else {
2550                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2551                 goto fail;
2552         }
2553
2554         cli_setpid(cli1, 1);
2555         cli_unlock(cli1, fnum1, 130, 4);
2556
2557         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2558         if (!NT_STATUS_IS_OK(status)) {
2559                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2560                 goto fail;
2561         } else {
2562                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2563         }
2564
2565         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2566         if (!NT_STATUS_IS_OK(status)) {
2567                 printf("pid1 unable to read the range 130:4, error was %s\n",
2568                       nt_errstr(status));
2569                 goto fail;
2570         } else if (nread != 4) {
2571                 printf("pid1 unable to read the range 130:4, "
2572                        "recv %ld req %d\n", (unsigned long)nread, 4);
2573                 goto fail;
2574         } else {
2575                 printf("pid1 successfully read the range 130:4\n");
2576         }
2577
2578         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2579         if (!NT_STATUS_IS_OK(status)) {
2580                 printf("pid1 unable to write to the range 130:4, error was "
2581                        "%s\n", nt_errstr(status));
2582                 goto fail;
2583         } else {
2584                 printf("pid1 successfully wrote to the range 130:4\n");
2585         }
2586
2587         cli_setpid(cli1, 2);
2588
2589         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2590         if (!NT_STATUS_IS_OK(status)) {
2591                 printf("pid2 unable to read the range 130:4, error was "
2592                        "%s\n", nt_errstr(status));
2593                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2594                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2595                         goto fail;
2596                 }
2597         } else {
2598                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2599                        (unsigned long)nread);
2600                 goto fail;
2601         }
2602
2603         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2604         if (!NT_STATUS_IS_OK(status)) {
2605                 printf("pid2 unable to write to the range 130:4, error was "
2606                        "%s\n", nt_errstr(status));
2607                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2608                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2609                         goto fail;
2610                 }
2611         } else {
2612                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2613                 goto fail;
2614         }
2615
2616         cli_unlock(cli1, fnum1, 130, 0);
2617         correct = True;
2618
2619 fail:
2620         cli_close(cli1, fnum1);
2621         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2622         torture_close_connection(cli1);
2623
2624         printf("finished locktest7\n");
2625         return correct;
2626 }
2627
2628 /*
2629  * This demonstrates a problem with our use of GPFS share modes: A file
2630  * descriptor sitting in the pending close queue holding a GPFS share mode
2631  * blocks opening a file another time. Happens with Word 2007 temp files.
2632  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2633  * open is denied with NT_STATUS_SHARING_VIOLATION.
2634  */
2635
2636 static bool run_locktest8(int dummy)
2637 {
2638         struct cli_state *cli1;
2639         const char *fname = "\\lockt8.lck";
2640         uint16_t fnum1, fnum2;
2641         char buf[200];
2642         bool correct = False;
2643         NTSTATUS status;
2644
2645         if (!torture_open_connection(&cli1, 0)) {
2646                 return False;
2647         }
2648
2649         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2650
2651         printf("starting locktest8\n");
2652
2653         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2654
2655         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2656                           &fnum1);
2657         if (!NT_STATUS_IS_OK(status)) {
2658                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2659                 return false;
2660         }
2661
2662         memset(buf, 0, sizeof(buf));
2663
2664         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2665         if (!NT_STATUS_IS_OK(status)) {
2666                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2667                           nt_errstr(status));
2668                 goto fail;
2669         }
2670
2671         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2672         if (!NT_STATUS_IS_OK(status)) {
2673                 printf("Unable to apply read lock on range 1:1, error was "
2674                        "%s\n", nt_errstr(status));
2675                 goto fail;
2676         }
2677
2678         status = cli_close(cli1, fnum1);
2679         if (!NT_STATUS_IS_OK(status)) {
2680                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2681                 goto fail;
2682         }
2683
2684         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2685         if (!NT_STATUS_IS_OK(status)) {
2686                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2687                           nt_errstr(status));
2688                 goto fail;
2689         }
2690
2691         correct = true;
2692
2693 fail:
2694         cli_close(cli1, fnum1);
2695         cli_close(cli1, fnum2);
2696         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2697         torture_close_connection(cli1);
2698
2699         printf("finished locktest8\n");
2700         return correct;
2701 }
2702
2703 /*
2704  * This test is designed to be run in conjunction with
2705  * external NFS or POSIX locks taken in the filesystem.
2706  * It checks that the smbd server will block until the
2707  * lock is released and then acquire it. JRA.
2708  */
2709
2710 static bool got_alarm;
2711 static struct cli_state *alarm_cli;
2712
2713 static void alarm_handler(int dummy)
2714 {
2715         got_alarm = True;
2716 }
2717
2718 static void alarm_handler_parent(int dummy)
2719 {
2720         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2721 }
2722
2723 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2724 {
2725         int fd;
2726         char c = '\0';
2727         struct flock lock;
2728         const char *local_pathname = NULL;
2729         int ret;
2730
2731         local_pathname = talloc_asprintf(talloc_tos(),
2732                         "%s/%s", local_path, fname);
2733         if (!local_pathname) {
2734                 printf("child: alloc fail\n");
2735                 exit(1);
2736         }
2737
2738         unlink(local_pathname);
2739         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2740         if (fd == -1) {
2741                 printf("child: open of %s failed %s.\n",
2742                         local_pathname, strerror(errno));
2743                 exit(1);
2744         }
2745
2746         /* Now take a fcntl lock. */
2747         lock.l_type = F_WRLCK;
2748         lock.l_whence = SEEK_SET;
2749         lock.l_start = 0;
2750         lock.l_len = 4;
2751         lock.l_pid = getpid();
2752
2753         ret = fcntl(fd,F_SETLK,&lock);
2754         if (ret == -1) {
2755                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2756                         local_pathname, strerror(errno));
2757                 exit(1);
2758         } else {
2759                 printf("child: got lock 0:4 on file %s.\n",
2760                         local_pathname );
2761                 fflush(stdout);
2762         }
2763
2764         CatchSignal(SIGALRM, alarm_handler);
2765         alarm(5);
2766         /* Signal the parent. */
2767         if (write(write_fd, &c, 1) != 1) {
2768                 printf("child: start signal fail %s.\n",
2769                         strerror(errno));
2770                 exit(1);
2771         }
2772         alarm(0);
2773
2774         alarm(10);
2775         /* Wait for the parent to be ready. */
2776         if (read(read_fd, &c, 1) != 1) {
2777                 printf("child: reply signal fail %s.\n",
2778                         strerror(errno));
2779                 exit(1);
2780         }
2781         alarm(0);
2782
2783         sleep(5);
2784         close(fd);
2785         printf("child: released lock 0:4 on file %s.\n",
2786                 local_pathname );
2787         fflush(stdout);
2788         exit(0);
2789 }
2790
2791 static bool _run_locktest9X(const char *fname, int timeout)
2792 {
2793         struct cli_state *cli1;
2794         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2795         uint16_t fnum;
2796         bool correct = False;
2797         int pipe_in[2], pipe_out[2];
2798         pid_t child_pid;
2799         char c = '\0';
2800         int ret;
2801         struct timeval start;
2802         double seconds;
2803         NTSTATUS status;
2804
2805         printf("starting locktest9X: %s\n", fname);
2806
2807         if (local_path == NULL) {
2808                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2809                 return false;
2810         }
2811
2812         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2813                 return false;
2814         }
2815
2816         child_pid = fork();
2817         if (child_pid == -1) {
2818                 return false;
2819         }
2820
2821         if (child_pid == 0) {
2822                 /* Child. */
2823                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2824                 exit(0);
2825         }
2826
2827         close(pipe_out[0]);
2828         close(pipe_in[1]);
2829         pipe_out[0] = -1;
2830         pipe_in[1] = -1;
2831
2832         /* Parent. */
2833         ret = read(pipe_in[0], &c, 1);
2834         if (ret != 1) {
2835                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2836                         strerror(errno));
2837                 return false;
2838         }
2839
2840         if (!torture_open_connection(&cli1, 0)) {
2841                 return false;
2842         }
2843
2844         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2845
2846         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2847                           &fnum);
2848         if (!NT_STATUS_IS_OK(status)) {
2849                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2850                 return false;
2851         }
2852
2853         /* Ensure the child has the lock. */
2854         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2855         if (NT_STATUS_IS_OK(status)) {
2856                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2857                 goto fail;
2858         } else {
2859                 d_printf("Child has the lock.\n");
2860         }
2861
2862         /* Tell the child to wait 5 seconds then exit. */
2863         ret = write(pipe_out[1], &c, 1);
2864         if (ret != 1) {
2865                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2866                         strerror(errno));
2867                 goto fail;
2868         }
2869
2870         /* Wait 20 seconds for the lock. */
2871         alarm_cli = cli1;
2872         CatchSignal(SIGALRM, alarm_handler_parent);
2873         alarm(20);
2874
2875         start = timeval_current();
2876
2877         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2878         if (!NT_STATUS_IS_OK(status)) {
2879                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2880                        "%s\n", nt_errstr(status));
2881                 goto fail_nofd;
2882         }
2883         alarm(0);
2884
2885         seconds = timeval_elapsed(&start);
2886
2887         printf("Parent got the lock after %.2f seconds.\n",
2888                 seconds);
2889
2890         status = cli_close(cli1, fnum);
2891         if (!NT_STATUS_IS_OK(status)) {
2892                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2893                 goto fail;
2894         }
2895
2896         correct = true;
2897
2898 fail:
2899         cli_close(cli1, fnum);
2900         torture_close_connection(cli1);
2901
2902 fail_nofd:
2903
2904         printf("finished locktest9X: %s\n", fname);
2905         return correct;
2906 }
2907
2908 static bool run_locktest9a(int dummy)
2909 {
2910         return _run_locktest9X("lock9a.dat", -1);
2911 }
2912
2913 static bool run_locktest9b(int dummy)
2914 {
2915         return _run_locktest9X("lock9b.dat", 10000);
2916 }
2917
2918 struct locktest10_state {
2919         bool ok;
2920         bool done;
2921 };
2922
2923 static void locktest10_lockingx_done(struct tevent_req *subreq);
2924 static void locktest10_read_andx_done(struct tevent_req *subreq);
2925
2926 static bool run_locktest10(int dummy)
2927 {
2928         struct tevent_context *ev = NULL;
2929         struct cli_state *cli1 = NULL;
2930         struct cli_state *cli2 = NULL;
2931         struct smb1_lock_element lck = { 0 };
2932         struct tevent_req *reqs[2] = { NULL };
2933         struct tevent_req *smbreqs[2] = { NULL };
2934         const char fname[] = "\\lockt10.lck";
2935         uint16_t fnum1, fnum2;
2936         bool ret = false;
2937         bool ok;
2938         uint8_t data = 1;
2939         struct locktest10_state state = { .ok = true };
2940         NTSTATUS status;
2941
2942         printf("starting locktest10\n");
2943
2944         ev = samba_tevent_context_init(NULL);
2945         if (ev == NULL) {
2946                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2947                 goto done;
2948         }
2949
2950         ok = torture_open_connection(&cli1, 0);
2951         if (!ok) {
2952                 goto done;
2953         }
2954         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2955
2956         ok = torture_open_connection(&cli2, 1);
2957         if (!ok) {
2958                 goto done;
2959         }
2960         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2961
2962         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2963         if (!NT_STATUS_IS_OK(status)) {
2964                 d_fprintf(stderr,
2965                           "cli_openx failed: %s\n",
2966                           nt_errstr(status));
2967                 goto done;
2968         }
2969
2970         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2971         if (!NT_STATUS_IS_OK(status)) {
2972                 d_fprintf(stderr,
2973                           "cli_writeall failed: %s\n",
2974                           nt_errstr(status));
2975                 goto done;
2976         }
2977
2978         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2979         if (!NT_STATUS_IS_OK(status)) {
2980                 d_fprintf(stderr,
2981                           "cli_openx failed: %s\n",
2982                           nt_errstr(status));
2983                 goto done;
2984         }
2985
2986         status = cli_locktype(
2987                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2988         if (!NT_STATUS_IS_OK(status)) {
2989                 d_fprintf(stderr,
2990                           "cli_locktype failed: %s\n",
2991                           nt_errstr(status));
2992                 goto done;
2993         }
2994
2995         lck = (struct smb1_lock_element) {
2996                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2997         };
2998
2999         reqs[0] = cli_lockingx_create(
3000                 ev,                             /* mem_ctx */
3001                 ev,                             /* tevent_context */
3002                 cli1,                           /* cli */
3003                 fnum1,                          /* fnum */
3004                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3005                 0,                              /* newoplocklevel */
3006                 1,                              /* timeout */
3007                 0,                              /* num_unlocks */
3008                 NULL,                           /* unlocks */
3009                 1,                              /* num_locks */
3010                 &lck,                           /* locks */
3011                 &smbreqs[0]);                   /* psmbreq */
3012         if (reqs[0] == NULL) {
3013                 d_fprintf(stderr, "cli_lockingx_create failed\n");
3014                 goto done;
3015         }
3016         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3017
3018         reqs[1] = cli_read_andx_create(
3019                 ev,             /* mem_ctx */
3020                 ev,             /* ev */
3021                 cli1,           /* cli */
3022                 fnum1,          /* fnum */
3023                 0,              /* offset */
3024                 1,              /* size */
3025                 &smbreqs[1]);   /* psmbreq */
3026         if (reqs[1] == NULL) {
3027                 d_fprintf(stderr, "cli_read_andx_create failed\n");
3028                 goto done;
3029         }
3030         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3031
3032         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3033         if (!NT_STATUS_IS_OK(status)) {
3034                 d_fprintf(stderr,
3035                           "smb1cli_req_chain_submit failed: %s\n",
3036                           nt_errstr(status));
3037                 goto done;
3038         }
3039
3040         while (!state.done) {
3041                 tevent_loop_once(ev);
3042         }
3043
3044         torture_close_connection(cli1);
3045
3046         if (state.ok) {
3047                 ret = true;
3048         }
3049 done:
3050         return ret;
3051 }
3052
3053 static void locktest10_lockingx_done(struct tevent_req *subreq)
3054 {
3055         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3056         NTSTATUS status;
3057
3058         status = cli_lockingx_recv(subreq);
3059         TALLOC_FREE(subreq);
3060
3061         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3062                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3063                 state->ok = false;
3064         }
3065 }
3066
3067 static void locktest10_read_andx_done(struct tevent_req *subreq)
3068 {
3069         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3070         ssize_t received = -1;
3071         uint8_t *rcvbuf = NULL;
3072         NTSTATUS status;
3073
3074         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3075
3076         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3077                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3078                 state->ok = false;
3079         }
3080
3081         state->done = true;
3082         TALLOC_FREE(subreq);
3083 }
3084
3085 static bool run_locktest11(int dummy)
3086 {
3087         struct cli_state *cli1;
3088         const char *fname = "\\lockt11.lck";
3089         NTSTATUS status;
3090         uint16_t fnum;
3091         bool ret = false;
3092
3093         if (!torture_open_connection(&cli1, 0)) {
3094                 return false;
3095         }
3096
3097         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3098
3099         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3100
3101         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3102         if (!NT_STATUS_IS_OK(status)) {
3103                 d_fprintf(stderr,
3104                           "cli_openx returned %s\n",
3105                           nt_errstr(status));
3106                 return false;
3107         }
3108
3109         /*
3110          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3111          * returns NT_STATUS_OK
3112          */
3113
3114         status = cli_lockingx(
3115                 cli1,                           /* cli */
3116                 fnum,                           /* fnum */
3117                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3118                 0,                              /* newoplocklevel */
3119                 0,                              /* timeout */
3120                 0,                              /* num_unlocks */
3121                 NULL,                           /* unlocks */
3122                 0,                              /* num_locks */
3123                 NULL);                          /* locks */
3124
3125         if (!NT_STATUS_IS_OK(status)) {
3126                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3127                 goto fail;
3128         }
3129
3130         ret = true;
3131 fail:
3132         cli_close(cli1, fnum);
3133         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3134
3135         return ret;
3136 }
3137
3138 struct deferred_close_state {
3139         struct tevent_context *ev;
3140         struct cli_state *cli;
3141         uint16_t fnum;
3142 };
3143
3144 static void deferred_close_waited(struct tevent_req *subreq);
3145 static void deferred_close_done(struct tevent_req *subreq);
3146
3147 static struct tevent_req *deferred_close_send(
3148         TALLOC_CTX *mem_ctx,
3149         struct tevent_context *ev,
3150         int wait_secs,
3151         struct cli_state *cli,
3152         uint16_t fnum)
3153 {
3154         struct tevent_req *req = NULL, *subreq = NULL;
3155         struct deferred_close_state *state = NULL;
3156         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3157
3158         req = tevent_req_create(
3159                 mem_ctx, &state, struct deferred_close_state);
3160         if (req == NULL) {
3161                 return NULL;
3162         }
3163         state->ev = ev;
3164         state->cli = cli;
3165         state->fnum = fnum;
3166
3167         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3168         if (tevent_req_nomem(subreq, req)) {
3169                 return tevent_req_post(req, ev);
3170         }
3171         tevent_req_set_callback(subreq, deferred_close_waited, req);
3172         return req;
3173 }
3174
3175 static void deferred_close_waited(struct tevent_req *subreq)
3176 {
3177         struct tevent_req *req = tevent_req_callback_data(
3178                 subreq, struct tevent_req);
3179         struct deferred_close_state *state = tevent_req_data(
3180                 req, struct deferred_close_state);
3181         bool ok;
3182
3183         ok = tevent_wakeup_recv(subreq);
3184         TALLOC_FREE(subreq);
3185         if (!ok) {
3186                 tevent_req_oom(req);
3187                 return;
3188         }
3189
3190         subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3191         if (tevent_req_nomem(subreq, req)) {
3192                 return;
3193         }
3194         tevent_req_set_callback(subreq, deferred_close_done, req);
3195 }
3196
3197 static void deferred_close_done(struct tevent_req *subreq)
3198 {
3199         NTSTATUS status = cli_close_recv(subreq);
3200         tevent_req_simple_finish_ntstatus(subreq, status);
3201 }
3202
3203 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3204 {
3205         return tevent_req_simple_recv_ntstatus(req);
3206 }
3207
3208 struct lockread_state {
3209         struct smb1_lock_element lck;
3210         struct tevent_req *reqs[2];
3211         struct tevent_req *smbreqs[2];
3212         NTSTATUS lock_status;
3213         NTSTATUS read_status;
3214         uint8_t *readbuf;
3215 };
3216
3217 static void lockread_lockingx_done(struct tevent_req *subreq);
3218 static void lockread_read_andx_done(struct tevent_req *subreq);
3219
3220 static struct tevent_req *lockread_send(
3221         TALLOC_CTX *mem_ctx,
3222         struct tevent_context *ev,
3223         struct cli_state *cli,
3224         uint16_t fnum)
3225 {
3226         struct tevent_req *req = NULL;
3227         struct lockread_state *state = NULL;
3228         NTSTATUS status;
3229
3230         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3231         if (req == NULL) {
3232                 return NULL;
3233         }
3234
3235         state->lck = (struct smb1_lock_element) {
3236                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3237         };
3238
3239         state->reqs[0] = cli_lockingx_create(
3240                 ev,                             /* mem_ctx */
3241                 ev,                             /* tevent_context */
3242                 cli,                            /* cli */
3243                 fnum,                           /* fnum */
3244                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3245                 0,                              /* newoplocklevel */
3246                 10000,                          /* timeout */
3247                 0,                              /* num_unlocks */
3248                 NULL,                           /* unlocks */
3249                 1,                              /* num_locks */
3250                 &state->lck,                    /* locks */
3251                 &state->smbreqs[0]);            /* psmbreq */
3252         if (tevent_req_nomem(state->reqs[0], req)) {
3253                 return tevent_req_post(req, ev);
3254         }
3255         tevent_req_set_callback(
3256                 state->reqs[0], lockread_lockingx_done, req);
3257
3258         state->reqs[1] = cli_read_andx_create(
3259                 ev,             /* mem_ctx */
3260                 ev,             /* ev */
3261                 cli,            /* cli */
3262                 fnum,           /* fnum */
3263                 0,              /* offset */
3264                 1,              /* size */
3265                 &state->smbreqs[1]);    /* psmbreq */
3266         if (tevent_req_nomem(state->reqs[1], req)) {
3267                 return tevent_req_post(req, ev);
3268         }
3269         tevent_req_set_callback(
3270                 state->reqs[1], lockread_read_andx_done, req);
3271
3272         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3273         if (tevent_req_nterror(req, status)) {
3274                 return tevent_req_post(req, ev);
3275         }
3276         return req;
3277 }
3278
3279 static void lockread_lockingx_done(struct tevent_req *subreq)
3280 {
3281         struct tevent_req *req = tevent_req_callback_data(
3282                 subreq, struct tevent_req);
3283         struct lockread_state *state = tevent_req_data(
3284                 req, struct lockread_state);
3285         state->lock_status = cli_lockingx_recv(subreq);
3286         TALLOC_FREE(subreq);
3287         d_fprintf(stderr,
3288                   "lockingx returned %s\n",
3289                   nt_errstr(state->lock_status));
3290 }
3291
3292 static void lockread_read_andx_done(struct tevent_req *subreq)
3293 {
3294         struct tevent_req *req = tevent_req_callback_data(
3295                 subreq, struct tevent_req);
3296         struct lockread_state *state = tevent_req_data(
3297                 req, struct lockread_state);
3298         ssize_t received = -1;
3299         uint8_t *rcvbuf = NULL;
3300
3301         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3302
3303         d_fprintf(stderr,
3304                   "read returned %s\n",
3305                   nt_errstr(state->read_status));
3306
3307         if (!NT_STATUS_IS_OK(state->read_status)) {
3308                 TALLOC_FREE(subreq);
3309                 tevent_req_done(req);
3310                 return;
3311         }
3312
3313         if (received > 0) {
3314                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3315                 TALLOC_FREE(subreq);
3316                 if (tevent_req_nomem(state->readbuf, req)) {
3317                         return;
3318                 }
3319         }
3320         TALLOC_FREE(subreq);
3321         tevent_req_done(req);
3322 }
3323
3324 static NTSTATUS lockread_recv(
3325         struct tevent_req *req,
3326         NTSTATUS *lock_status,
3327         NTSTATUS *read_status,
3328         TALLOC_CTX *mem_ctx,
3329         uint8_t **read_buf)
3330 {
3331         struct lockread_state *state = tevent_req_data(
3332                 req, struct lockread_state);
3333         NTSTATUS status;
3334
3335         if (tevent_req_is_nterror(req, &status)) {
3336                 return status;
3337         }
3338
3339         *lock_status = state->lock_status;
3340         *read_status = state->read_status;
3341         if (state->readbuf != NULL) {
3342                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3343         } else {
3344                 *read_buf = NULL;
3345         }
3346
3347         return NT_STATUS_OK;
3348 }
3349
3350 struct lock12_state {
3351         uint8_t dummy;
3352 };
3353
3354 static void lock12_closed(struct tevent_req *subreq);
3355 static void lock12_read(struct tevent_req *subreq);
3356
3357 static struct tevent_req *lock12_send(
3358         TALLOC_CTX *mem_ctx,
3359         struct tevent_context *ev,
3360         struct cli_state *cli,
3361         uint16_t fnum1,
3362         uint16_t fnum2)
3363 {
3364         struct tevent_req *req = NULL, *subreq = NULL;
3365         struct lock12_state *state = NULL;
3366
3367         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3368         if (req == NULL) {
3369                 return NULL;
3370         }
3371
3372         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3373         if (tevent_req_nomem(subreq, req)) {
3374                 return tevent_req_post(req, ev);
3375         }
3376         tevent_req_set_callback(subreq, lock12_closed, req);
3377
3378         subreq = lockread_send(state, ev, cli, fnum2);
3379         if (tevent_req_nomem(subreq, req)) {
3380                 return tevent_req_post(req, ev);
3381         }
3382         tevent_req_set_callback(subreq, lock12_read, req);
3383
3384         return req;
3385 }
3386
3387 static void lock12_closed(struct tevent_req *subreq)
3388 {
3389         struct tevent_req *req = tevent_req_callback_data(
3390                 subreq, struct tevent_req);
3391         NTSTATUS status;
3392
3393         status = deferred_close_recv(subreq);
3394         TALLOC_FREE(subreq);
3395         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3396         if (tevent_req_nterror(req, status)) {
3397                 return;
3398         }
3399 }
3400
3401 static void lock12_read(struct tevent_req *subreq)
3402 {
3403         struct tevent_req *req = tevent_req_callback_data(
3404                 subreq, struct tevent_req);
3405         struct lock12_state *state = tevent_req_data(
3406                 req, struct lock12_state);
3407         NTSTATUS status, lock_status, read_status;
3408         uint8_t *buf = NULL;
3409
3410         status = lockread_recv(
3411                 subreq, &lock_status, &read_status, state, &buf);
3412         TALLOC_FREE(subreq);
3413         if (tevent_req_nterror(req, status) ||
3414             tevent_req_nterror(req, lock_status) ||
3415             tevent_req_nterror(req, read_status)) {
3416                 return;
3417         }
3418         tevent_req_done(req);
3419 }
3420
3421 static NTSTATUS lock12_recv(struct tevent_req *req)
3422
3423 {
3424         NTSTATUS status;
3425
3426         if (tevent_req_is_nterror(req, &status)) {
3427                 return status;
3428         }
3429         return NT_STATUS_OK;
3430 }
3431
3432 static bool run_locktest12(int dummy)
3433 {
3434         struct tevent_context *ev = NULL;
3435         struct tevent_req *req = NULL;
3436         struct cli_state *cli = NULL;
3437         const char fname[] = "\\lockt12.lck";
3438         uint16_t fnum1, fnum2;
3439         bool ret = false;
3440         bool ok;
3441         uint8_t data = 1;
3442         NTSTATUS status;
3443
3444         printf("starting locktest12\n");
3445
3446         ev = samba_tevent_context_init(NULL);
3447         if (ev == NULL) {
3448                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3449                 goto done;
3450         }
3451
3452         ok = torture_open_connection(&cli, 0);
3453         if (!ok) {
3454                 goto done;
3455         }
3456         smbXcli_conn_set_sockopt(cli->conn, sockops);
3457
3458         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3459         if (!NT_STATUS_IS_OK(status)) {
3460                 d_fprintf(stderr,
3461                           "cli_openx failed: %s\n",
3462                           nt_errstr(status));
3463                 goto done;
3464         }
3465
3466         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3467         if (!NT_STATUS_IS_OK(status)) {
3468                 d_fprintf(stderr,
3469                           "cli_openx failed: %s\n",
3470                           nt_errstr(status));
3471                 goto done;
3472         }
3473
3474         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3475         if (!NT_STATUS_IS_OK(status)) {
3476                 d_fprintf(stderr,
3477                           "cli_writeall failed: %s\n",
3478                           nt_errstr(status));
3479                 goto done;
3480         }
3481
3482         status = cli_locktype(
3483                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3484         if (!NT_STATUS_IS_OK(status)) {
3485                 d_fprintf(stderr,
3486                           "cli_locktype failed: %s\n",
3487                           nt_errstr(status));
3488                 goto done;
3489         }
3490
3491         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3492         if (req == NULL) {
3493                 d_fprintf(stderr, "lock12_send failed\n");
3494                 goto done;
3495         }
3496
3497         ok = tevent_req_poll_ntstatus(req, ev, &status);
3498         if (!ok) {
3499                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3500                 goto done;
3501         }
3502
3503         if (!NT_STATUS_IS_OK(status)) {
3504                 d_fprintf(stderr,
3505                           "tevent_req_poll_ntstatus returned %s\n",
3506                           nt_errstr(status));
3507                 goto done;
3508         }
3509
3510         status = lock12_recv(req);
3511         if (!NT_STATUS_IS_OK(status)) {
3512                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3513                 goto done;
3514         }
3515
3516         ret = true;
3517 done:
3518         if (cli != NULL) {
3519                 torture_close_connection(cli);
3520         }
3521         return ret;
3522 }
3523
3524 struct lock_ntcancel_state {
3525         struct timeval start;
3526         struct smb1_lock_element lck;
3527         struct tevent_req *subreq;
3528 };
3529
3530 static void lock_ntcancel_waited(struct tevent_req *subreq);
3531 static void lock_ntcancel_done(struct tevent_req *subreq);
3532
3533 static struct tevent_req *lock_ntcancel_send(
3534         TALLOC_CTX *mem_ctx,
3535         struct tevent_context *ev,
3536         struct cli_state *cli,
3537         uint16_t fnum)
3538 {
3539         struct tevent_req *req = NULL, *subreq = NULL;
3540         struct lock_ntcancel_state *state = NULL;
3541
3542         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3543         if (req == NULL) {
3544                 return NULL;
3545         }
3546         state->lck = (struct smb1_lock_element) {
3547                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3548         };
3549         state->start = timeval_current();
3550
3551         state->subreq = cli_lockingx_send(
3552                 state,                          /* mem_ctx */
3553                 ev,                             /* tevent_context */
3554                 cli,                            /* cli */
3555                 fnum,                           /* fnum */
3556                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3557                 0,                              /* newoplocklevel */
3558                 10000,                          /* timeout */
3559                 0,                              /* num_unlocks */
3560                 NULL,                           /* unlocks */
3561                 1,                              /* num_locks */
3562                 &state->lck);                   /* locks */
3563         if (tevent_req_nomem(state->subreq, req)) {
3564                 return tevent_req_post(req, ev);
3565         }
3566         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3567
3568         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3569         if (tevent_req_nomem(subreq, req)) {
3570                 return tevent_req_post(req, ev);
3571         }
3572         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3573         return req;
3574 }
3575
3576 static void lock_ntcancel_waited(struct tevent_req *subreq)
3577 {
3578         struct tevent_req *req = tevent_req_callback_data(
3579                 subreq, struct tevent_req);
3580         struct lock_ntcancel_state *state = tevent_req_data(
3581                 req, struct lock_ntcancel_state);
3582         bool ok;
3583
3584         ok = tevent_wakeup_recv(subreq);
3585         TALLOC_FREE(subreq);
3586         if (!ok) {
3587                 tevent_req_oom(req);
3588                 return;
3589         }
3590
3591         ok = tevent_req_cancel(state->subreq);
3592         if (!ok) {
3593                 d_fprintf(stderr, "Could not cancel subreq\n");
3594                 tevent_req_oom(req);
3595                 return;
3596         }
3597 }
3598
3599 static void lock_ntcancel_done(struct tevent_req *subreq)
3600 {
3601         struct tevent_req *req = tevent_req_callback_data(
3602                 subreq, struct tevent_req);
3603         struct lock_ntcancel_state *state = tevent_req_data(
3604                 req, struct lock_ntcancel_state);
3605         NTSTATUS status;
3606         double elapsed;
3607
3608         status = cli_lockingx_recv(subreq);
3609         TALLOC_FREE(subreq);
3610
3611         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3612                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3613                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3614                 return;
3615         }
3616
3617         elapsed = timeval_elapsed(&state->start);
3618
3619         if (elapsed > 3) {
3620                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3621                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3622                 return;
3623         }
3624
3625         tevent_req_done(req);
3626 }
3627
3628 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3629 {
3630         return tevent_req_simple_recv_ntstatus(req);
3631 }
3632
3633 static bool run_locktest13(int dummy)
3634 {
3635         struct tevent_context *ev = NULL;
3636         struct tevent_req *req = NULL;
3637         struct cli_state *cli = NULL;
3638         const char fname[] = "\\lockt13.lck";
3639         uint16_t fnum1, fnum2;
3640         bool ret = false;
3641         bool ok;
3642         uint8_t data = 1;
3643         NTSTATUS status;
3644
3645         printf("starting locktest13\n");
3646
3647         ev = samba_tevent_context_init(NULL);
3648         if (ev == NULL) {
3649                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3650                 goto done;
3651         }
3652
3653         ok = torture_open_connection(&cli, 0);
3654         if (!ok) {
3655                 goto done;
3656         }
3657         smbXcli_conn_set_sockopt(cli->conn, sockops);
3658
3659         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3660         if (!NT_STATUS_IS_OK(status)) {
3661                 d_fprintf(stderr,
3662                           "cli_openx failed: %s\n",
3663                           nt_errstr(status));
3664                 goto done;
3665         }
3666
3667         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3668         if (!NT_STATUS_IS_OK(status)) {
3669                 d_fprintf(stderr,
3670                           "cli_openx failed: %s\n",
3671                           nt_errstr(status));
3672                 goto done;
3673         }
3674
3675         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3676         if (!NT_STATUS_IS_OK(status)) {
3677                 d_fprintf(stderr,
3678                           "cli_writeall failed: %s\n",
3679                           nt_errstr(status));
3680                 goto done;
3681         }
3682
3683         status = cli_locktype(
3684                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3685         if (!NT_STATUS_IS_OK(status)) {
3686                 d_fprintf(stderr,
3687                           "cli_locktype failed: %s\n",
3688                           nt_errstr(status));
3689                 goto done;
3690         }
3691
3692         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3693         if (req == NULL) {
3694                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3695                 goto done;
3696         }
3697
3698         ok = tevent_req_poll_ntstatus(req, ev, &status);
3699         if (!ok) {
3700                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3701                 goto done;
3702         }
3703
3704         if (!NT_STATUS_IS_OK(status)) {
3705                 d_fprintf(stderr,
3706                           "tevent_req_poll_ntstatus returned %s\n",
3707                           nt_errstr(status));
3708                 goto done;
3709         }
3710
3711         status = lock_ntcancel_recv(req);
3712         if (!NT_STATUS_IS_OK(status)) {
3713                 d_fprintf(stderr,
3714                           "lock_ntcancel returned %s\n",
3715                           nt_errstr(status));
3716                 goto done;
3717         }
3718
3719         ret = true;
3720 done:
3721         if (cli != NULL) {
3722                 torture_close_connection(cli);
3723         }
3724         return ret;
3725 }
3726
3727 /*
3728 test whether fnums and tids open on one VC are available on another (a major
3729 security hole)
3730 */
3731 static bool run_fdpasstest(int dummy)
3732 {
3733         struct cli_state *cli1, *cli2;
3734         const char *fname = "\\fdpass.tst";
3735         uint16_t fnum1;
3736         char buf[1024];
3737         NTSTATUS status;
3738
3739         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3740                 return False;
3741         }
3742         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3743         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3744
3745         printf("starting fdpasstest\n");
3746
3747         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3748
3749         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3750                           &fnum1);
3751         if (!NT_STATUS_IS_OK(status)) {
3752                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3753                 return False;
3754         }
3755
3756         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3757                               13, NULL);
3758         if (!NT_STATUS_IS_OK(status)) {
3759                 printf("write failed (%s)\n", nt_errstr(status));
3760                 return False;
3761         }
3762
3763         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3764         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3765         cli_setpid(cli2, cli_getpid(cli1));
3766
3767         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3768                 printf("read succeeded! nasty security hole [%s]\n", buf);
3769                 return false;
3770         }
3771
3772         cli_close(cli1, fnum1);
3773         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3774
3775         torture_close_connection(cli1);
3776         torture_close_connection(cli2);
3777
3778         printf("finished fdpasstest\n");
3779         return True;
3780 }
3781
3782 static bool run_fdsesstest(int dummy)
3783 {
3784         struct cli_state *cli;
3785         uint16_t new_vuid;
3786         uint16_t saved_vuid;
3787         uint32_t new_cnum;
3788         uint32_t saved_cnum;
3789         const char *fname = "\\fdsess.tst";
3790         const char *fname1 = "\\fdsess1.tst";
3791         uint16_t fnum1;
3792         uint16_t fnum2;
3793         char buf[1024];
3794         bool ret = True;
3795         NTSTATUS status;
3796
3797         if (!torture_open_connection(&cli, 0))
3798                 return False;
3799         smbXcli_conn_set_sockopt(cli->conn, sockops);
3800
3801         if (!torture_cli_session_setup2(cli, &new_vuid))
3802                 return False;
3803
3804         saved_cnum = cli_state_get_tid(cli);
3805         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3806                 return False;
3807         new_cnum = cli_state_get_tid(cli);
3808         cli_state_set_tid(cli, saved_cnum);
3809
3810         printf("starting fdsesstest\n");
3811
3812         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3813         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3814
3815         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3816         if (!NT_STATUS_IS_OK(status)) {
3817                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3818                 return False;
3819         }
3820
3821         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3822                               NULL);
3823         if (!NT_STATUS_IS_OK(status)) {
3824                 printf("write failed (%s)\n", nt_errstr(status));
3825                 return False;
3826         }
3827
3828         saved_vuid = cli_state_get_uid(cli);
3829         cli_state_set_uid(cli, new_vuid);
3830
3831         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3832                 printf("read succeeded with different vuid! "
3833                        "nasty security hole [%s]\n", buf);
3834                 ret = false;
3835         }
3836         /* Try to open a file with different vuid, samba cnum. */
3837         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3838                 printf("create with different vuid, same cnum succeeded.\n");
3839                 cli_close(cli, fnum2);
3840                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3841         } else {
3842                 printf("create with different vuid, same cnum failed.\n");
3843                 printf("This will cause problems with service clients.\n");
3844                 ret = False;
3845         }
3846
3847         cli_state_set_uid(cli, saved_vuid);
3848
3849         /* Try with same vuid, different cnum. */
3850         cli_state_set_tid(cli, new_cnum);
3851
3852         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3853                 printf("read succeeded with different cnum![%s]\n", buf);
3854                 ret = false;
3855         }
3856
3857         cli_state_set_tid(cli, saved_cnum);
3858         cli_close(cli, fnum1);
3859         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3860
3861         torture_close_connection(cli);
3862
3863         printf("finished fdsesstest\n");
3864         return ret;
3865 }
3866
3867 /*
3868   This test checks that
3869
3870   1) the server does not allow an unlink on a file that is open
3871 */
3872 static bool run_unlinktest(int dummy)
3873 {
3874         struct cli_state *cli;
3875         const char *fname = "\\unlink.tst";
3876         uint16_t fnum;
3877         bool correct = True;
3878         NTSTATUS status;
3879
3880         if (!torture_open_connection(&cli, 0)) {
3881                 return False;
3882         }
3883
3884         smbXcli_conn_set_sockopt(cli->conn, sockops);
3885
3886         printf("starting unlink test\n");
3887
3888         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3889
3890         cli_setpid(cli, 1);
3891
3892         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3893         if (!NT_STATUS_IS_OK(status)) {
3894                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3895                 return False;
3896         }
3897
3898         status = cli_unlink(cli, fname,
3899                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3900         if (NT_STATUS_IS_OK(status)) {
3901                 printf("error: server allowed unlink on an open file\n");
3902                 correct = False;
3903         } else {
3904                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3905                                       NT_STATUS_SHARING_VIOLATION);
3906         }
3907
3908         cli_close(cli, fnum);
3909         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3910
3911         if (!torture_close_connection(cli)) {
3912                 correct = False;
3913         }
3914
3915         printf("unlink test finished\n");
3916
3917         return correct;
3918 }
3919
3920
3921 /*
3922 test how many open files this server supports on the one socket
3923 */
3924 static bool run_maxfidtest(int dummy)
3925 {
3926         struct cli_state *cli;
3927         fstring fname;
3928         uint16_t fnums[0x11000];
3929         int i;
3930         int retries=4;
3931         bool correct = True;
3932         NTSTATUS status;
3933
3934         cli = current_cli;
3935
3936         if (retries <= 0) {
3937                 printf("failed to connect\n");
3938                 return False;
3939         }
3940
3941         smbXcli_conn_set_sockopt(cli->conn, sockops);
3942
3943         for (i=0; i<0x11000; i++) {
3944                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3945                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3946                                   &fnums[i]);
3947                 if (!NT_STATUS_IS_OK(status)) {
3948                         printf("open of %s failed (%s)\n",
3949                                fname, nt_errstr(status));
3950                         printf("maximum fnum is %d\n", i);
3951                         break;
3952                 }
3953                 printf("%6d\r", i);
3954         }
3955         printf("%6d\n", i);
3956         i--;
3957
3958         printf("cleaning up\n");
3959         for (;i>=0;i--) {
3960                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3961                 cli_close(cli, fnums[i]);
3962
3963                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3964                 if (!NT_STATUS_IS_OK(status)) {
3965                         printf("unlink of %s failed (%s)\n",
3966                                fname, nt_errstr(status));
3967                         correct = False;
3968                 }
3969                 printf("%6d\r", i);
3970         }
3971         printf("%6d\n", 0);
3972
3973         printf("maxfid test finished\n");
3974         if (!torture_close_connection(cli)) {
3975                 correct = False;
3976         }
3977         return correct;
3978 }
3979
3980 /* generate a random buffer */
3981 static void rand_buf(char *buf, int len)
3982 {
3983         while (len--) {
3984                 *buf = (char)sys_random();
3985                 buf++;
3986         }
3987 }
3988
3989 /* send smb negprot commands, not reading the response */
3990 static bool run_negprot_nowait(int dummy)
3991 {
3992         struct tevent_context *ev;
3993         int i;
3994         struct cli_state *cli;
3995         bool correct = True;
3996
3997         printf("starting negprot nowait test\n");
3998
3999         ev = samba_tevent_context_init(talloc_tos());
4000         if (ev == NULL) {
4001                 return false;
4002         }
4003
4004         if (!(cli = open_nbt_connection())) {
4005                 TALLOC_FREE(ev);
4006                 return False;
4007         }
4008
4009         for (i=0;i<50000;i++) {
4010                 struct tevent_req *req;
4011
4012                 req = smbXcli_negprot_send(
4013                         ev,
4014                         ev,
4015                         cli->conn,
4016                         cli->timeout,
4017                         PROTOCOL_CORE,
4018                         PROTOCOL_NT1,
4019                         0,
4020                         NULL);
4021                 if (req == NULL) {
4022                         TALLOC_FREE(ev);
4023                         return false;
4024                 }
4025                 if (!tevent_req_poll(req, ev)) {
4026                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4027                                   strerror(errno));
4028                         TALLOC_FREE(ev);
4029                         return false;
4030                 }
4031                 TALLOC_FREE(req);
4032         }
4033
4034         if (torture_close_connection(cli)) {
4035                 correct = False;
4036         }
4037
4038         printf("finished negprot nowait test\n");
4039
4040         return correct;
4041 }
4042
4043 /* send smb negprot commands, not reading the response */
4044 static bool run_bad_nbt_session(int dummy)
4045 {
4046         struct nmb_name called, calling;
4047         struct sockaddr_storage ss;
4048         NTSTATUS status;
4049         int fd;
4050         bool ret;
4051
4052         printf("starting bad nbt session test\n");
4053
4054         make_nmb_name(&calling, myname, 0x0);
4055         make_nmb_name(&called , host, 0x20);
4056
4057         if (!resolve_name(host, &ss, 0x20, true)) {
4058                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4059                 return false;
4060         }
4061
4062         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4063         if (!NT_STATUS_IS_OK(status)) {
4064                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4065                           nt_errstr(status));
4066                 return false;
4067         }
4068
4069         ret = cli_bad_session_request(fd, &calling, &called);
4070         close(fd);
4071         if (!ret) {
4072                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4073                           nt_errstr(status));
4074                 return false;
4075         }
4076
4077         printf("finished bad nbt session test\n");
4078         return true;
4079 }
4080
4081 /* send random IPC commands */
4082 static bool run_randomipc(int dummy)
4083 {
4084         char *rparam = NULL;
4085         char *rdata = NULL;
4086         unsigned int rdrcnt,rprcnt;
4087         char param[1024];
4088         int api, param_len, i;
4089         struct cli_state *cli;
4090         bool correct = True;
4091         int count = 50000;
4092
4093         printf("starting random ipc test\n");
4094
4095         if (!torture_open_connection(&cli, 0)) {
4096                 return False;
4097         }
4098
4099         for (i=0;i<count;i++) {
4100                 api = sys_random() % 500;
4101                 param_len = (sys_random() % 64);
4102
4103                 rand_buf(param, param_len);
4104
4105                 SSVAL(param,0,api);
4106
4107                 cli_api(cli,
4108                         param, param_len, 8,
4109                         NULL, 0, CLI_BUFFER_SIZE,
4110                         &rparam, &rprcnt,
4111                         &rdata, &rdrcnt);
4112                 if (i % 100 == 0) {
4113                         printf("%d/%d\r", i,count);
4114                 }
4115         }
4116         printf("%d/%d\n", i, count);
4117
4118         if (!torture_close_connection(cli)) {
4119                 correct = False;
4120         }
4121
4122         SAFE_FREE(rparam);
4123         SAFE_FREE(rdata);
4124
4125         printf("finished random ipc test\n");
4126
4127         return correct;
4128 }
4129
4130
4131
4132 static void browse_callback(const char *sname, uint32_t stype,
4133                             const char *comment, void *state)
4134 {
4135         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4136 }
4137
4138
4139
4140 /*
4141   This test checks the browse list code
4142
4143 */
4144 static bool run_browsetest(int dummy)
4145 {
4146         static struct cli_state *cli;
4147         bool correct = True;
4148
4149         printf("starting browse test\n");
4150
4151         if (!torture_open_connection(&cli, 0)) {
4152                 return False;
4153         }
4154
4155         printf("domain list:\n");
4156         cli_NetServerEnum(cli, cli->server_domain,
4157                           SV_TYPE_DOMAIN_ENUM,
4158                           browse_callback, NULL);
4159
4160         printf("machine list:\n");
4161         cli_NetServerEnum(cli, cli->server_domain,
4162                           SV_TYPE_ALL,
4163                           browse_callback, NULL);
4164
4165         if (!torture_close_connection(cli)) {
4166                 correct = False;
4167         }
4168
4169         printf("browse test finished\n");
4170
4171         return correct;
4172
4173 }
4174
4175 static bool check_attributes(struct cli_state *cli,
4176                                 const char *fname,
4177                                 uint32_t expected_attrs)
4178 {
4179         uint32_t attrs = 0;
4180         NTSTATUS status = cli_getatr(cli,
4181                                 fname,
4182                                 &attrs,
4183                                 NULL,
4184                                 NULL);
4185         if (!NT_STATUS_IS_OK(status)) {
4186                 printf("cli_getatr failed with %s\n",
4187                         nt_errstr(status));
4188                 return false;
4189         }
4190         if (attrs != expected_attrs) {
4191                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4192                         (unsigned int)attrs,
4193                         (unsigned int)expected_attrs);
4194                 return false;
4195         }
4196         return true;
4197 }
4198
4199 /*
4200   This checks how the getatr calls works
4201 */
4202 static bool run_attrtest(int dummy)
4203 {
4204         struct cli_state *cli;
4205         uint16_t fnum;
4206         time_t t, t2;
4207         const char *fname = "\\attrib123456789.tst";
4208         bool correct = True;
4209         NTSTATUS status;
4210
4211         printf("starting attrib test\n");
4212
4213         if (!torture_open_connection(&cli, 0)) {
4214                 return False;
4215         }
4216
4217         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4218         status = cli_unlink(cli, fname, 0x20000);
4219         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4220                 correct = false;
4221                 goto out;
4222         }
4223
4224         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4225         cli_openx(cli, fname,
4226                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4227         cli_close(cli, fnum);
4228
4229         status = cli_getatr(cli, fname, NULL, NULL, &t);
4230         if (!NT_STATUS_IS_OK(status)) {
4231                 printf("getatr failed (%s)\n", nt_errstr(status));
4232                 correct = False;
4233         }
4234
4235         if (labs(t - time(NULL)) > 60*60*24*10) {
4236                 printf("ERROR: SMBgetatr bug. time is %s",
4237                        ctime(&t));
4238                 t = time(NULL);
4239                 correct = True;
4240         }
4241
4242         t2 = t-60*60*24; /* 1 day ago */
4243
4244         /* Ensure we can't set with out-of-range (unknown) attribute. */
4245         status = cli_setatr(cli, fname, 0x20000, t2);
4246         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4247                 correct = false;
4248                 goto out;
4249         }
4250
4251         status = cli_setatr(cli, fname, 0, t2);
4252         if (!NT_STATUS_IS_OK(status)) {
4253                 printf("setatr failed (%s)\n", nt_errstr(status));
4254                 correct = True;
4255         }
4256
4257         status = cli_getatr(cli, fname, NULL, NULL, &t);
4258         if (!NT_STATUS_IS_OK(status)) {
4259                 printf("getatr failed (%s)\n", nt_errstr(status));
4260                 correct = True;
4261         }
4262
4263         if (t != t2) {
4264                 printf("ERROR: getatr/setatr bug. times are\n%s",
4265                        ctime(&t));
4266                 printf("%s", ctime(&t2));
4267                 correct = True;
4268         }
4269
4270         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4271
4272         /* Check cli_setpathinfo_ext() */
4273         /* Re-create the file. */
4274         status = cli_openx(cli, fname,
4275                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4276         if (!NT_STATUS_IS_OK(status)) {
4277                 printf("Failed to recreate %s (%s)\n",
4278                         fname, nt_errstr(status));
4279                 correct = false;
4280         }
4281         cli_close(cli, fnum);
4282
4283         status = cli_setpathinfo_ext(
4284                 cli,
4285                 fname,
4286                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4287                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4288                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4289                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4290                 FILE_ATTRIBUTE_SYSTEM |
4291                 FILE_ATTRIBUTE_HIDDEN |
4292                 FILE_ATTRIBUTE_READONLY);
4293         if (!NT_STATUS_IS_OK(status)) {
4294                 printf("cli_setpathinfo_ext failed with %s\n",
4295                         nt_errstr(status));
4296                 correct = false;
4297         }
4298
4299         /* Check attributes are correct. */
4300         correct = check_attributes(cli,
4301                         fname,
4302                         FILE_ATTRIBUTE_SYSTEM |
4303                         FILE_ATTRIBUTE_HIDDEN |
4304                         FILE_ATTRIBUTE_READONLY);
4305         if (correct == false) {
4306                 goto out;
4307         }
4308
4309         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4310         status = cli_setpathinfo_ext(
4311                 cli,
4312                 fname,
4313                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4314                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4315                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4316                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4317                 FILE_ATTRIBUTE_NORMAL);
4318         if (!NT_STATUS_IS_OK(status)) {
4319                 printf("cli_setpathinfo_ext failed with %s\n",
4320                         nt_errstr(status));
4321                 correct = false;
4322         }
4323
4324         /* Check attributes are correct. */
4325         correct = check_attributes(cli,
4326                         fname,
4327                         FILE_ATTRIBUTE_SYSTEM |
4328                         FILE_ATTRIBUTE_HIDDEN |
4329                         FILE_ATTRIBUTE_READONLY);
4330         if (correct == false) {
4331                 goto out;
4332         }
4333
4334         /* Setting to (uint16_t)-1 should also be ignored. */
4335         status = cli_setpathinfo_ext(
4336                 cli,
4337                 fname,
4338                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4339                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4340                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4341                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4342                 (uint32_t)-1);
4343         if (!NT_STATUS_IS_OK(status)) {
4344                 printf("cli_setpathinfo_ext failed with %s\n",
4345                         nt_errstr(status));
4346                 correct = false;
4347         }
4348
4349         /* Check attributes are correct. */
4350         correct = check_attributes(cli,
4351                         fname,
4352                         FILE_ATTRIBUTE_SYSTEM |
4353                         FILE_ATTRIBUTE_HIDDEN |
4354                         FILE_ATTRIBUTE_READONLY);
4355         if (correct == false) {
4356                 goto out;
4357         }
4358
4359         /* Setting to 0 should clear them all. */
4360         status = cli_setpathinfo_ext(
4361                 cli,
4362                 fname,
4363                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4364                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4365                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4366                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4367                 0);
4368         if (!NT_STATUS_IS_OK(status)) {
4369                 printf("cli_setpathinfo_ext failed with %s\n",
4370                         nt_errstr(status));
4371                 correct = false;
4372         }
4373
4374         /* Check attributes are correct. */
4375         correct = check_attributes(cli,
4376                         fname,
4377                         FILE_ATTRIBUTE_NORMAL);
4378         if (correct == false) {
4379                 goto out;
4380         }
4381
4382   out:
4383
4384         cli_unlink(cli,
4385                 fname,
4386                 FILE_ATTRIBUTE_SYSTEM |
4387                 FILE_ATTRIBUTE_HIDDEN|
4388                 FILE_ATTRIBUTE_READONLY);
4389
4390         if (!torture_close_connection(cli)) {
4391                 correct = False;
4392         }
4393
4394         printf("attrib test finished\n");
4395
4396         return correct;
4397 }
4398
4399 static NTSTATUS cli_qfilename(
4400         struct cli_state *cli,
4401         uint16_t fnum,
4402         TALLOC_CTX *mem_ctx,
4403         char **_name)
4404 {
4405         uint16_t recv_flags2;
4406         uint8_t *rdata;
4407         uint32_t num_rdata;
4408         NTSTATUS status;
4409         char *name = NULL;
4410         uint32_t namelen;
4411
4412         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4413                                SMB_QUERY_FILE_NAME_INFO,
4414                                4, CLI_BUFFER_SIZE, &recv_flags2,
4415                                &rdata, &num_rdata);
4416         if (!NT_STATUS_IS_OK(status)) {
4417                 return status;
4418         }
4419
4420         namelen = IVAL(rdata, 0);
4421         if (namelen > (num_rdata - 4)) {
4422                 TALLOC_FREE(rdata);
4423                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4424         }
4425
4426         pull_string_talloc(mem_ctx,
4427                            (const char *)rdata,
4428                            recv_flags2,
4429                            &name,
4430                            rdata + 4,
4431                            namelen,
4432                            STR_UNICODE);
4433         if (name == NULL) {
4434                 status = map_nt_error_from_unix(errno);
4435                 TALLOC_FREE(rdata);
4436                 return status;
4437         }
4438
4439         *_name = name;
4440         TALLOC_FREE(rdata);
4441         return NT_STATUS_OK;
4442 }
4443
4444 /*
4445   This checks a couple of trans2 calls
4446 */
4447 static bool run_trans2test(int dummy)
4448 {
4449         struct cli_state *cli;
4450         uint16_t fnum;
4451         off_t size;
4452         time_t c_time, a_time, m_time;
4453         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4454         const char *fname = "\\trans2.tst";
4455         const char *dname = "\\trans2";
4456         const char *fname2 = "\\trans2\\trans2.tst";
4457         char *pname = NULL;
4458         bool correct = True;
4459         NTSTATUS status;
4460         uint32_t fs_attr;
4461         uint64_t ino;
4462
4463         printf("starting trans2 test\n");
4464
4465         if (!torture_open_connection(&cli, 0)) {
4466                 return False;
4467         }
4468
4469         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4470                 /* Ensure ino is zero, SMB2 gets a real one. */
4471                 ino = 0;
4472         } else {
4473                 /* Ensure ino is -1, SMB1 never gets a real one. */
4474                 ino = (uint64_t)-1;
4475         }
4476
4477         status = cli_get_fs_attr_info(cli, &fs_attr);
4478         if (!NT_STATUS_IS_OK(status)) {
4479                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4480                        nt_errstr(status));
4481                 correct = false;
4482         }
4483
4484         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4485         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4486         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4487                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4488         if (!NT_STATUS_IS_OK(status)) {
4489                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4490                 correct = False;
4491         }
4492
4493         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4494         if (!NT_STATUS_IS_OK(status)) {
4495                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4496                 correct = False;
4497         }
4498         else if (strcmp(pname, fname)) {
4499                 printf("qfilename gave different name? [%s] [%s]\n",
4500                        fname, pname);
4501                 correct = False;
4502         }
4503
4504         cli_close(cli, fnum);
4505
4506         sleep(2);
4507
4508         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4509         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4510                           &fnum);
4511         if (!NT_STATUS_IS_OK(status)) {
4512                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4513                 return False;
4514         }
4515         cli_close(cli, fnum);
4516
4517         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4518                                 NULL);
4519         if (!NT_STATUS_IS_OK(status)) {
4520                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4521                 correct = False;
4522         } else {
4523                 time_t t = time(NULL);
4524
4525                 if (c_time != m_time) {
4526                         printf("create time=%s", ctime(&c_time));
4527                         printf("modify time=%s", ctime(&m_time));
4528                         printf("This system appears to have sticky create times\n");
4529                 }
4530                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4531                         printf("access time=%s", ctime(&a_time));
4532                         printf("This system appears to set a midnight access time\n");
4533                         correct = False;
4534                 }
4535
4536                 if (labs(m_time - t) > 60*60*24*7) {
4537                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4538                         correct = False;
4539                 }
4540         }
4541
4542
4543         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4544         cli_openx(cli, fname,
4545                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4546         cli_close(cli, fnum);
4547         status = cli_qpathinfo2(cli,
4548                                 fname,
4549                                 &c_time_ts,
4550                                 &a_time_ts,
4551                                 &w_time_ts,
4552                                 &m_time_ts,
4553                                 &size,
4554                                 NULL,
4555                                 &ino,
4556                                 NULL);
4557         if (!NT_STATUS_IS_OK(status)) {
4558                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4559                 correct = False;
4560         } else {
4561                 if (w_time_ts.tv_sec < 60*60*24*2) {
4562                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4563                         printf("This system appears to set a initial 0 write time\n");
4564                         correct = False;
4565                 }
4566                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4567                         /* SMB2 should always return an inode. */
4568                         if (ino == 0) {
4569                                 printf("SMB2 bad inode (0)\n");
4570                                 correct = false;
4571                         }
4572                 } else {
4573                         /* SMB1 must always return zero here. */
4574                         if (ino != 0) {
4575                                 printf("SMB1 bad inode (!0)\n");
4576                                 correct = false;
4577                         }
4578                 }
4579         }
4580
4581         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4582
4583
4584         /* check if the server updates the directory modification time
4585            when creating a new file */
4586         status = cli_mkdir(cli, dname);
4587         if (!NT_STATUS_IS_OK(status)) {
4588                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4589                 correct = False;
4590         }
4591         sleep(3);
4592         status = cli_qpathinfo2(cli,
4593                                 "\\trans2\\",
4594                                 &c_time_ts,
4595                                 &a_time_ts,
4596                                 &w_time_ts,
4597                                 &m_time_ts,
4598                                 &size,
4599                                 NULL,
4600                                 NULL,
4601                                 NULL);
4602         if (!NT_STATUS_IS_OK(status)) {
4603                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4604                 correct = False;
4605         }
4606
4607         cli_openx(cli, fname2,
4608                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4609         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4610         cli_close(cli, fnum);
4611         status = cli_qpathinfo2(cli,
4612                                 "\\trans2\\",
4613                                 &c_time_ts,
4614                                 &a_time_ts,
4615                                 &w_time_ts,
4616                                 &m_time2_ts,
4617                                 &size,
4618                                 NULL,
4619                                 NULL,
4620                                 NULL);
4621         if (!NT_STATUS_IS_OK(status)) {
4622                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4623                 correct = False;
4624         } else {
4625                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4626                     == 0) {
4627                         printf("This system does not update directory modification times\n");
4628                         correct = False;
4629                 }
4630         }
4631         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4632         cli_rmdir(cli, dname);
4633
4634         if (!torture_close_connection(cli)) {
4635                 correct = False;
4636         }
4637
4638         printf("trans2 test finished\n");
4639
4640         return correct;
4641 }
4642
4643 /*
4644   This checks new W2K calls.
4645 */
4646
4647 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4648 {
4649         uint8_t *buf = NULL;
4650         uint32_t len;
4651         NTSTATUS status;
4652
4653         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4654                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4655         if (!NT_STATUS_IS_OK(status)) {
4656                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4657                        nt_errstr(status));
4658         } else {
4659                 printf("qfileinfo: level %d, len = %u\n", level, len);
4660                 dump_data(0, (uint8_t *)buf, len);
4661                 printf("\n");
4662         }
4663         TALLOC_FREE(buf);
4664         return status;
4665 }
4666
4667 static bool run_w2ktest(int dummy)
4668 {
4669         struct cli_state *cli;
4670         uint16_t fnum;
4671         const char *fname = "\\w2ktest\\w2k.tst";
4672         int level;
4673         bool correct = True;
4674
4675         printf("starting w2k test\n");
4676
4677         if (!torture_open_connection(&cli, 0)) {
4678                 return False;
4679         }
4680
4681         cli_openx(cli, fname,
4682                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4683
4684         for (level = 1004; level < 1040; level++) {
4685                 new_trans(cli, fnum, level);
4686         }
4687
4688         cli_close(cli, fnum);
4689
4690         if (!torture_close_connection(cli)) {
4691                 correct = False;
4692         }
4693
4694         printf("w2k test finished\n");
4695
4696         return correct;
4697 }
4698
4699
4700 /*
4701   this is a harness for some oplock tests
4702  */
4703 static bool run_oplock1(int dummy)
4704 {
4705         struct cli_state *cli1;
4706         const char *fname = "\\lockt1.lck";
4707         uint16_t fnum1;
4708         bool correct = True;
4709         NTSTATUS status;
4710
4711         printf("starting oplock test 1\n");
4712
4713         if (!torture_open_connection(&cli1, 0)) {
4714                 return False;
4715         }
4716
4717         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4718
4719         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4720
4721         cli1->use_oplocks = True;
4722
4723         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4724                           &fnum1);
4725         if (!NT_STATUS_IS_OK(status)) {
4726                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4727                 return False;
4728         }
4729
4730         cli1->use_oplocks = False;
4731
4732         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4733         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4734
4735         status = cli_close(cli1, fnum1);
4736         if (!NT_STATUS_IS_OK(status)) {
4737                 printf("close2 failed (%s)\n", nt_errstr(status));
4738                 return False;
4739         }
4740
4741         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4742         if (!NT_STATUS_IS_OK(status)) {
4743                 printf("unlink failed (%s)\n", nt_errstr(status));
4744                 return False;
4745         }
4746
4747         if (!torture_close_connection(cli1)) {
4748                 correct = False;
4749         }
4750
4751         printf("finished oplock test 1\n");
4752
4753         return correct;
4754 }
4755
4756 static bool run_oplock2(int dummy)
4757 {
4758         struct cli_state *cli1, *cli2;
4759         const char *fname = "\\lockt2.lck";
4760         uint16_t fnum1, fnum2;
4761         int saved_use_oplocks = use_oplocks;
4762         char buf[4];
4763         bool correct = True;
4764         volatile bool *shared_correct;
4765         size_t nread;
4766         NTSTATUS status;
4767
4768         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4769         *shared_correct = True;
4770
4771         use_level_II_oplocks = True;
4772         use_oplocks = True;
4773
4774         printf("starting oplock test 2\n");
4775
4776         if (!torture_open_connection(&cli1, 0)) {
4777                 use_level_II_oplocks = False;
4778                 use_oplocks = saved_use_oplocks;
4779                 return False;
4780         }
4781
4782         if (!torture_open_connection(&cli2, 1)) {
4783                 use_level_II_oplocks = False;
4784                 use_oplocks = saved_use_oplocks;
4785                 return False;
4786         }
4787
4788         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4789
4790         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4791         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4792
4793         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4794                           &fnum1);
4795         if (!NT_STATUS_IS_OK(status)) {
4796                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4797                 return False;
4798         }
4799
4800         /* Don't need the globals any more. */
4801         use_level_II_oplocks = False;
4802         use_oplocks = saved_use_oplocks;
4803
4804         if (fork() == 0) {
4805                 /* Child code */
4806                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4807                 if (!NT_STATUS_IS_OK(status)) {
4808                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4809                         *shared_correct = False;
4810                         exit(0);
4811                 }
4812
4813                 sleep(2);
4814
4815                 status = cli_close(cli2, fnum2);
4816                 if (!NT_STATUS_IS_OK(status)) {
4817                         printf("close2 failed (%s)\n", nt_errstr(status));
4818                         *shared_correct = False;
4819                 }
4820
4821                 exit(0);
4822         }
4823
4824         sleep(2);
4825
4826         /* Ensure cli1 processes the break. Empty file should always return 0
4827          * bytes.  */
4828         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4829         if (!NT_STATUS_IS_OK(status)) {
4830                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4831                 correct = false;
4832         } else if (nread != 0) {
4833                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4834                       (unsigned long)nread, 0);
4835                 correct = false;
4836         }
4837
4838         /* Should now be at level II. */
4839         /* Test if sending a write locks causes a break to none. */
4840         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4841         if (!NT_STATUS_IS_OK(status)) {
4842                 printf("lock failed (%s)\n", nt_errstr(status));
4843                 correct = False;
4844         }
4845
4846         cli_unlock(cli1, fnum1, 0, 4);
4847
4848         sleep(2);
4849
4850         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4851         if (!NT_STATUS_IS_OK(status)) {
4852                 printf("lock failed (%s)\n", nt_errstr(status));
4853                 correct = False;
4854         }
4855
4856         cli_unlock(cli1, fnum1, 0, 4);
4857
4858         sleep(2);
4859
4860         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4861
4862         status = cli_close(cli1, fnum1);
4863         if (!NT_STATUS_IS_OK(status)) {
4864                 printf("close1 failed (%s)\n", nt_errstr(status));
4865                 correct = False;
4866         }
4867
4868         sleep(4);
4869
4870         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4871         if (!NT_STATUS_IS_OK(status)) {
4872                 printf("unlink failed (%s)\n", nt_errstr(status));
4873                 correct = False;
4874         }
4875
4876         if (!torture_close_connection(cli1)) {
4877                 correct = False;
4878         }
4879
4880         if (!*shared_correct) {
4881                 correct = False;
4882         }
4883
4884         printf("finished oplock test 2\n");
4885
4886         return correct;
4887 }
4888
4889 struct oplock4_state {
4890         struct tevent_context *ev;
4891         struct cli_state *cli;
4892         bool *got_break;
4893         uint16_t *fnum2;
4894 };
4895
4896 static void oplock4_got_break(struct tevent_req *req);
4897 static void oplock4_got_open(struct tevent_req *req);
4898
4899 static bool run_oplock4(int dummy)
4900 {
4901         struct tevent_context *ev;
4902         struct cli_state *cli1, *cli2;
4903         struct tevent_req *oplock_req, *open_req;
4904         const char *fname = "\\lockt4.lck";
4905         const char *fname_ln = "\\lockt4_ln.lck";
4906         uint16_t fnum1, fnum2;
4907         int saved_use_oplocks = use_oplocks;
4908         NTSTATUS status;
4909         bool correct = true;
4910
4911         bool got_break;
4912
4913         struct oplock4_state *state;
4914
4915         printf("starting oplock test 4\n");
4916
4917         if (!torture_open_connection(&cli1, 0)) {
4918                 use_level_II_oplocks = false;
4919                 use_oplocks = saved_use_oplocks;
4920                 return false;
4921         }
4922
4923         if (!torture_open_connection(&cli2, 1)) {
4924                 use_level_II_oplocks = false;
4925                 use_oplocks = saved_use_oplocks;
4926                 return false;
4927         }
4928
4929         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4930         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4931
4932         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4933         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4934
4935         /* Create the file. */
4936         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4937                           &fnum1);
4938         if (!NT_STATUS_IS_OK(status)) {
4939                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4940                 return false;
4941         }
4942
4943         status = cli_close(cli1, fnum1);
4944         if (!NT_STATUS_IS_OK(status)) {
4945                 printf("close1 failed (%s)\n", nt_errstr(status));
4946                 return false;
4947         }
4948
4949         /* Now create a hardlink. */
4950         status = cli_hardlink(cli1, fname, fname_ln);
4951         if (!NT_STATUS_IS_OK(status)) {
4952                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4953                 return false;
4954         }
4955
4956         /* Prove that opening hardlinks cause deny modes to conflict. */
4957         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4958         if (!NT_STATUS_IS_OK(status)) {
4959                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4960                 return false;
4961         }
4962
4963         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4964         if (NT_STATUS_IS_OK(status)) {
4965                 printf("open of %s succeeded - should fail with sharing violation.\n",
4966                         fname_ln);
4967                 return false;
4968         }
4969
4970         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4971                 printf("open of %s should fail with sharing violation. Got %s\n",
4972                         fname_ln, nt_errstr(status));
4973                 return false;
4974         }
4975
4976         status = cli_close(cli1, fnum1);
4977         if (!NT_STATUS_IS_OK(status)) {
4978                 printf("close1 failed (%s)\n", nt_errstr(status));
4979                 return false;
4980         }
4981
4982         cli1->use_oplocks = true;
4983         cli2->use_oplocks = true;
4984
4985         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4986         if (!NT_STATUS_IS_OK(status)) {
4987                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4988                 return false;
4989         }
4990
4991         ev = samba_tevent_context_init(talloc_tos());
4992         if (ev == NULL) {
4993                 printf("tevent_context_init failed\n");
4994                 return false;
4995         }
4996
4997         state = talloc(ev, struct oplock4_state);
4998         if (state == NULL) {
4999                 printf("talloc failed\n");
5000                 return false;
5001         }
5002         state->ev = ev;
5003         state->cli = cli1;
5004         state->got_break = &got_break;
5005         state->fnum2 = &fnum2;
5006
5007         oplock_req = cli_smb_oplock_break_waiter_send(
5008                 talloc_tos(), ev, cli1);
5009         if (oplock_req == NULL) {
5010                 printf("cli_smb_oplock_break_waiter_send failed\n");
5011                 return false;
5012         }
5013         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5014
5015         open_req = cli_openx_send(
5016                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5017         if (open_req == NULL) {
5018                 printf("cli_openx_send failed\n");
5019                 return false;
5020         }
5021         tevent_req_set_callback(open_req, oplock4_got_open, state);
5022
5023         got_break = false;
5024         fnum2 = 0xffff;
5025
5026         while (!got_break || fnum2 == 0xffff) {
5027                 int ret;
5028                 ret = tevent_loop_once(ev);
5029                 if (ret == -1) {
5030                         printf("tevent_loop_once failed: %s\n",
5031                                strerror(errno));
5032                         return false;
5033                 }
5034         }
5035
5036         status = cli_close(cli2, fnum2);
5037         if (!NT_STATUS_IS_OK(status)) {
5038                 printf("close2 failed (%s)\n", nt_errstr(status));
5039                 correct = false;
5040         }
5041
5042         status = cli_close(cli1, fnum1);
5043         if (!NT_STATUS_IS_OK(status)) {
5044                 printf("close1 failed (%s)\n", nt_errstr(status));
5045                 correct = false;
5046         }
5047
5048         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5049         if (!NT_STATUS_IS_OK(status)) {
5050                 printf("unlink failed (%s)\n", nt_errstr(status));
5051                 correct = false;
5052         }
5053
5054         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5055         if (!NT_STATUS_IS_OK(status)) {
5056                 printf("unlink failed (%s)\n", nt_errstr(status));
5057                 correct = false;
5058         }
5059
5060         if (!torture_close_connection(cli1)) {
5061                 correct = false;
5062         }
5063
5064         if (!got_break) {
5065                 correct = false;
5066         }
5067
5068         printf("finished oplock test 4\n");
5069
5070         return correct;
5071 }
5072
5073 static void oplock4_got_break(struct tevent_req *req)
5074 {
5075         struct oplock4_state *state = tevent_req_callback_data(
5076                 req, struct oplock4_state);
5077         uint16_t fnum;
5078         uint8_t level;
5079         NTSTATUS status;
5080
5081         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5082         TALLOC_FREE(req);
5083         if (!NT_STATUS_IS_OK(status)) {
5084                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5085                        nt_errstr(status));
5086                 return;
5087         }
5088         *state->got_break = true;
5089
5090         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5091                                   NO_OPLOCK);
5092         if (req == NULL) {
5093                 printf("cli_oplock_ack_send failed\n");
5094                 return;
5095         }
5096 }
5097
5098 static void oplock4_got_open(struct tevent_req *req)
5099 {
5100         struct oplock4_state *state = tevent_req_callback_data(
5101                 req, struct oplock4_state);
5102         NTSTATUS status;
5103
5104         status = cli_openx_recv(req, state->fnum2);
5105         if (!NT_STATUS_IS_OK(status)) {
5106                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5107                 *state->fnum2 = 0xffff;
5108         }
5109 }
5110
5111 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5112
5113 struct oplock5_state {
5114         int pipe_down_fd;
5115 };
5116
5117 /*
5118  * Async open the file that has a kernel oplock, do an echo to get
5119  * that 100% across, close the file to signal to the child fd that the
5120  * oplock can be dropped, wait for the open reply.
5121  */
5122
5123 static void oplock5_opened(struct tevent_req *subreq);
5124 static void oplock5_pong(struct tevent_req *subreq);
5125 static void oplock5_timedout(struct tevent_req *subreq);
5126
5127 static struct tevent_req *oplock5_send(
5128         TALLOC_CTX *mem_ctx,
5129         struct tevent_context *ev,
5130         struct cli_state *cli,
5131         const char *fname,
5132         int pipe_down_fd)
5133 {
5134         struct tevent_req *req = NULL, *subreq = NULL;
5135         struct oplock5_state *state = NULL;
5136         static uint8_t data = 0;
5137
5138         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5139         if (req == NULL) {
5140                 return NULL;
5141         }
5142         state->pipe_down_fd = pipe_down_fd;
5143
5144         subreq = cli_ntcreate_send(
5145                 state,
5146                 ev,
5147                 cli,
5148                 fname,
5149                 0,                      /* CreatFlags */
5150                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5151                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5152                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5153                 FILE_OPEN,               /* CreateDisposition */
5154                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5155                 0,                       /* Impersonation */
5156                 0);                      /* SecurityFlags */
5157         if (tevent_req_nomem(subreq, req)) {
5158                 return tevent_req_post(req, ev);
5159         }
5160         tevent_req_set_callback(subreq, oplock5_opened, req);
5161
5162         subreq = cli_echo_send(
5163                 state,
5164                 ev,
5165                 cli,
5166                 1,
5167                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5168         if (tevent_req_nomem(subreq, req)) {
5169                 return tevent_req_post(req, ev);
5170         }
5171         tevent_req_set_callback(subreq, oplock5_pong, req);
5172
5173         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5174         if (tevent_req_nomem(subreq, req)) {
5175                 return tevent_req_post(req, ev);
5176         }
5177         tevent_req_set_callback(subreq, oplock5_timedout, req);
5178
5179         return req;
5180 }
5181
5182 static void oplock5_opened(struct tevent_req *subreq)
5183 {
5184         struct tevent_req *req = tevent_req_callback_data(
5185                 subreq, struct tevent_req);
5186         NTSTATUS status;
5187         uint16_t fnum;
5188
5189         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5190         TALLOC_FREE(subreq);
5191         if (tevent_req_nterror(req, status)) {
5192                 return;
5193         }
5194         tevent_req_done(req);
5195 }
5196
5197 static void oplock5_pong(struct tevent_req *subreq)
5198 {
5199         struct tevent_req *req = tevent_req_callback_data(
5200                 subreq, struct tevent_req);
5201         struct oplock5_state *state = tevent_req_data(
5202                 req, struct oplock5_state);
5203         NTSTATUS status;
5204
5205         status = cli_echo_recv(subreq);
5206         TALLOC_FREE(subreq);
5207         if (tevent_req_nterror(req, status)) {
5208                 return;
5209         }
5210
5211         close(state->pipe_down_fd);
5212 }
5213
5214 static void oplock5_timedout(struct tevent_req *subreq)
5215 {
5216         struct tevent_req *req = tevent_req_callback_data(
5217                 subreq, struct tevent_req);
5218         bool ok;
5219
5220         ok = tevent_wakeup_recv(subreq);
5221         TALLOC_FREE(subreq);
5222         if (!ok) {
5223                 tevent_req_oom(req);
5224                 return;
5225         }
5226         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5227 }
5228
5229 static NTSTATUS oplock5_recv(struct tevent_req *req)
5230 {
5231         return tevent_req_simple_recv_ntstatus(req);
5232 }
5233
5234 static bool run_oplock5(int dummy)
5235 {
5236         struct tevent_context *ev = NULL;
5237         struct tevent_req *req = NULL;
5238         struct cli_state *cli = NULL;
5239         const char *fname = "oplock5.txt";
5240         int pipe_down[2], pipe_up[2];
5241         pid_t child_pid;
5242         uint8_t c = '\0';
5243         NTSTATUS status;
5244         int ret;
5245         bool ok;
5246
5247         printf("starting oplock5\n");
5248
5249         if (local_path == NULL) {
5250                 d_fprintf(stderr, "oplock5 must be given a local path via "
5251                           "-l <localpath>\n");
5252                 return false;
5253         }
5254
5255         ret = pipe(pipe_down);
5256         if (ret == -1) {
5257                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5258                 return false;
5259         }
5260         ret = pipe(pipe_up);
5261         if (ret == -1) {
5262                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5263                 return false;
5264         }
5265
5266         child_pid = fork();
5267         if (child_pid == -1) {
5268                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5269                 return false;
5270         }
5271
5272         if (child_pid == 0) {
5273                 char *local_file = NULL;
5274                 int fd;
5275
5276                 close(pipe_down[1]);
5277                 close(pipe_up[0]);
5278
5279                 local_file = talloc_asprintf(
5280                         talloc_tos(), "%s/%s", local_path, fname);
5281                 if (local_file == 0) {
5282                         c = 1;
5283                         goto do_write;
5284                 }
5285                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5286                 if (fd == -1) {
5287                         d_fprintf(stderr,
5288                                   "open(%s) in child failed: %s\n",
5289                                   local_file,
5290                                   strerror(errno));
5291                         c = 2;
5292                         goto do_write;
5293                 }
5294
5295                 signal(SIGIO, SIG_IGN);
5296
5297                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5298                 if (ret == -1) {
5299                         d_fprintf(stderr,
5300                                   "SETLEASE in child failed: %s\n",
5301                                   strerror(errno));
5302                         c = 3;
5303                         goto do_write;
5304                 }
5305
5306         do_write:
5307                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5308                 if (ret == -1) {
5309                         d_fprintf(stderr,
5310                                   "sys_write failed: %s\n",
5311                                   strerror(errno));
5312                         exit(4);
5313                 }
5314                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5315                 if (ret == -1) {
5316                         d_fprintf(stderr,
5317                                   "sys_read failed: %s\n",
5318                                   strerror(errno));
5319                         exit(5);
5320                 }
5321                 exit(0);
5322         }
5323
5324         close(pipe_up[1]);
5325         close(pipe_down[0]);
5326
5327         ret = sys_read(pipe_up[0], &c, sizeof(c));
5328         if (ret != 1) {
5329                 d_fprintf(stderr,
5330                           "sys_read failed: %s\n",
5331                           strerror(errno));
5332                 return false;
5333         }
5334         if (c != 0) {
5335                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5336                 return false;
5337         }
5338
5339         ok = torture_open_connection(&cli, 0);
5340         if (!ok) {
5341                 d_fprintf(stderr, "torture_open_connection failed\n");
5342                 return false;
5343         }
5344
5345         ev = samba_tevent_context_init(talloc_tos());
5346         if (ev == NULL) {
5347                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5348                 return false;
5349         }
5350
5351         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5352         if (req == NULL) {
5353                 d_fprintf(stderr, "oplock5_send failed\n");
5354                 return false;
5355         }
5356
5357         ok = tevent_req_poll_ntstatus(req, ev, &status);
5358         if (!ok) {
5359                 d_fprintf(stderr,
5360                           "tevent_req_poll_ntstatus failed: %s\n",
5361                           nt_errstr(status));
5362                 return false;
5363         }
5364
5365         status = oplock5_recv(req);
5366         TALLOC_FREE(req);
5367         if (!NT_STATUS_IS_OK(status)) {
5368                 d_fprintf(stderr,
5369                           "oplock5 failed: %s\n",
5370                           nt_errstr(status));
5371                 return false;
5372         }
5373
5374         return true;
5375 }
5376
5377 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5378
5379 /*
5380   Test delete on close semantics.
5381  */
5382 static bool run_deletetest(int dummy)
5383 {
5384         struct cli_state *cli1 = NULL;
5385         struct cli_state *cli2 = NULL;
5386         const char *fname = "\\delete.file";
5387         uint16_t fnum1 = (uint16_t)-1;
5388         uint16_t fnum2 = (uint16_t)-1;
5389         bool correct = false;
5390         NTSTATUS status;
5391
5392         printf("starting delete test\n");
5393
5394         if (!torture_open_connection(&cli1, 0)) {
5395                 return False;
5396         }
5397
5398         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5399
5400         /* Test 1 - this should delete the file on close. */
5401
5402         cli_setatr(cli1, fname, 0, 0);
5403         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5404
5405         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5406                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5407                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5408         if (!NT_STATUS_IS_OK(status)) {
5409                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5410                 goto fail;
5411         }
5412
5413         status = cli_close(cli1, fnum1);
5414         if (!NT_STATUS_IS_OK(status)) {
5415                 printf("[1] close failed (%s)\n", nt_errstr(status));
5416                 goto fail;
5417         }
5418
5419         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5420         if (NT_STATUS_IS_OK(status)) {
5421                 printf("[1] open of %s succeeded (should fail)\n", fname);
5422                 goto fail;
5423         }
5424
5425         printf("first delete on close test succeeded.\n");
5426
5427         /* Test 2 - this should delete the file on close. */
5428
5429         cli_setatr(cli1, fname, 0, 0);
5430         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5431
5432         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5433                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5434                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5435         if (!NT_STATUS_IS_OK(status)) {
5436                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5437                 goto fail;
5438         }
5439
5440         status = cli_nt_delete_on_close(cli1, fnum1, true);
5441         if (!NT_STATUS_IS_OK(status)) {
5442                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5443                 goto fail;
5444         }
5445
5446         status = cli_close(cli1, fnum1);
5447         if (!NT_STATUS_IS_OK(status)) {
5448                 printf("[2] close failed (%s)\n", nt_errstr(status));
5449                 goto fail;
5450         }
5451
5452         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5453         if (NT_STATUS_IS_OK(status)) {
5454                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5455                 status = cli_close(cli1, fnum1);
5456                 if (!NT_STATUS_IS_OK(status)) {
5457                         printf("[2] close failed (%s)\n", nt_errstr(status));
5458                 }
5459                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5460                 goto fail;
5461         }
5462
5463         printf("second delete on close test succeeded.\n");
5464
5465         /* Test 3 - ... */
5466         cli_setatr(cli1, fname, 0, 0);
5467         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5468
5469         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5470                               FILE_ATTRIBUTE_NORMAL,
5471                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5472                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5473         if (!NT_STATUS_IS_OK(status)) {
5474                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5475                 goto fail;
5476         }
5477
5478         /* This should fail with a sharing violation - open for delete is only compatible
5479            with SHARE_DELETE. */
5480
5481         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5482                               FILE_ATTRIBUTE_NORMAL,
5483                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5484                               FILE_OPEN, 0, 0, &fnum2, NULL);
5485         if (NT_STATUS_IS_OK(status)) {
5486                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5487                 goto fail;
5488         }
5489
5490         /* This should succeed. */
5491         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5492                              FILE_ATTRIBUTE_NORMAL,
5493                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5494                              FILE_OPEN, 0, 0, &fnum2, NULL);
5495         if (!NT_STATUS_IS_OK(status)) {
5496                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5497                 goto fail;
5498         }
5499
5500         status = cli_nt_delete_on_close(cli1, fnum1, true);
5501         if (!NT_STATUS_IS_OK(status)) {
5502                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5503                 goto fail;
5504         }
5505
5506         status = cli_close(cli1, fnum1);
5507         if (!NT_STATUS_IS_OK(status)) {
5508                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5509                 goto fail;
5510         }
5511
5512         status = cli_close(cli1, fnum2);
5513         if (!NT_STATUS_IS_OK(status)) {
5514                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5515                 goto fail;
5516         }
5517
5518         /* This should fail - file should no longer be there. */
5519
5520         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5521         if (NT_STATUS_IS_OK(status)) {
5522                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5523                 status = cli_close(cli1, fnum1);
5524                 if (!NT_STATUS_IS_OK(status)) {
5525                         printf("[3] close failed (%s)\n", nt_errstr(status));
5526                 }
5527                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5528                 goto fail;
5529         }
5530
5531         printf("third delete on close test succeeded.\n");
5532
5533         /* Test 4 ... */
5534         cli_setatr(cli1, fname, 0, 0);
5535         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5536
5537         status = cli_ntcreate(cli1, fname, 0,
5538                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5539                               FILE_ATTRIBUTE_NORMAL,
5540                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5541                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5542         if (!NT_STATUS_IS_OK(status)) {
5543                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5544                 goto fail;
5545         }
5546
5547         /* This should succeed. */
5548         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5549                              FILE_ATTRIBUTE_NORMAL,
5550                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5551                              FILE_OPEN, 0, 0, &fnum2, NULL);
5552         if (!NT_STATUS_IS_OK(status)) {
5553                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5554                 goto fail;
5555         }
5556
5557         status = cli_close(cli1, fnum2);
5558         if (!NT_STATUS_IS_OK(status)) {
5559                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5560                 goto fail;
5561         }
5562
5563         status = cli_nt_delete_on_close(cli1, fnum1, true);
5564         if (!NT_STATUS_IS_OK(status)) {
5565                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5566                 goto fail;
5567         }
5568
5569         /* This should fail - no more opens once delete on close set. */
5570         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5571                               FILE_ATTRIBUTE_NORMAL,
5572                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5573                               FILE_OPEN, 0, 0, &fnum2, NULL);
5574         if (NT_STATUS_IS_OK(status)) {
5575                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5576                 goto fail;
5577         }
5578
5579         status = cli_close(cli1, fnum1);
5580         if (!NT_STATUS_IS_OK(status)) {
5581                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5582                 goto fail;
5583         }
5584
5585         printf("fourth delete on close test succeeded.\n");
5586
5587         /* Test 5 ... */
5588         cli_setatr(cli1, fname, 0, 0);
5589         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5590
5591         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5592         if (!NT_STATUS_IS_OK(status)) {
5593                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5594                 goto fail;
5595         }
5596
5597         /* This should fail - only allowed on NT opens with DELETE access. */
5598
5599         status = cli_nt_delete_on_close(cli1, fnum1, true);
5600         if (NT_STATUS_IS_OK(status)) {
5601                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5602                 goto fail;
5603         }
5604
5605         status = cli_close(cli1, fnum1);
5606         if (!NT_STATUS_IS_OK(status)) {
5607                 printf("[5] close failed (%s)\n", nt_errstr(status));
5608                 goto fail;
5609         }
5610
5611         printf("fifth delete on close test succeeded.\n");
5612
5613         /* Test 6 ... */
5614         cli_setatr(cli1, fname, 0, 0);
5615         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5616
5617         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5618                              FILE_ATTRIBUTE_NORMAL,
5619                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5620                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5621         if (!NT_STATUS_IS_OK(status)) {
5622                 printf("[6] open of %s failed (%s)\n", fname,
5623                        nt_errstr(status));
5624                 goto fail;
5625         }
5626
5627         /* This should fail - only allowed on NT opens with DELETE access. */
5628
5629         status = cli_nt_delete_on_close(cli1, fnum1, true);
5630         if (NT_STATUS_IS_OK(status)) {
5631                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5632                 goto fail;
5633         }
5634
5635         status = cli_close(cli1, fnum1);
5636         if (!NT_STATUS_IS_OK(status)) {
5637                 printf("[6] close failed (%s)\n", nt_errstr(status));
5638                 goto fail;
5639         }
5640
5641         printf("sixth delete on close test succeeded.\n");
5642
5643         /* Test 7 ... */
5644         cli_setatr(cli1, fname, 0, 0);
5645         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5646
5647         status = cli_ntcreate(cli1, fname, 0,
5648                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5649                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5650                               0, 0, &fnum1, NULL);
5651         if (!NT_STATUS_IS_OK(status)) {
5652                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5653                 goto fail;
5654         }
5655
5656         status = cli_nt_delete_on_close(cli1, fnum1, true);
5657         if (!NT_STATUS_IS_OK(status)) {
5658                 printf("[7] setting delete_on_close on file failed !\n");
5659                 goto fail;
5660         }
5661
5662         status = cli_nt_delete_on_close(cli1, fnum1, false);
5663         if (!NT_STATUS_IS_OK(status)) {
5664                 printf("[7] unsetting delete_on_close on file failed !\n");
5665                 goto fail;
5666         }
5667
5668         status = cli_close(cli1, fnum1);
5669         if (!NT_STATUS_IS_OK(status)) {
5670                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5671                 goto fail;
5672         }
5673
5674         /* This next open should succeed - we reset the flag. */
5675         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5676         if (!NT_STATUS_IS_OK(status)) {
5677                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5678                 goto fail;
5679         }
5680
5681         status = cli_close(cli1, fnum1);
5682         if (!NT_STATUS_IS_OK(status)) {
5683                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5684                 goto fail;
5685         }
5686
5687         printf("seventh delete on close test succeeded.\n");
5688
5689         /* Test 8 ... */
5690         cli_setatr(cli1, fname, 0, 0);
5691         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5692
5693         if (!torture_open_connection(&cli2, 1)) {
5694                 printf("[8] failed to open second connection.\n");
5695                 goto fail;
5696         }
5697
5698         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5699
5700         status = cli_ntcreate(cli1, fname, 0,
5701                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5702                              FILE_ATTRIBUTE_NORMAL,
5703                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5704                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5705         if (!NT_STATUS_IS_OK(status)) {
5706                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5707                 goto fail;
5708         }
5709
5710         status = cli_ntcreate(cli2, fname, 0,
5711                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5712                              FILE_ATTRIBUTE_NORMAL,
5713                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5714                              FILE_OPEN, 0, 0, &fnum2, NULL);
5715         if (!NT_STATUS_IS_OK(status)) {
5716                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5717                 goto fail;
5718         }
5719
5720         status = cli_nt_delete_on_close(cli1, fnum1, true);
5721         if (!NT_STATUS_IS_OK(status)) {
5722                 printf("[8] setting delete_on_close on file failed !\n");
5723                 goto fail;
5724         }
5725
5726         status = cli_close(cli1, fnum1);
5727         if (!NT_STATUS_IS_OK(status)) {
5728                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5729                 goto fail;
5730         }
5731
5732         status = cli_close(cli2, fnum2);
5733         if (!NT_STATUS_IS_OK(status)) {
5734                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5735                 goto fail;
5736         }
5737
5738         /* This should fail.. */
5739         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5740         if (NT_STATUS_IS_OK(status)) {
5741                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5742                 goto fail;
5743         }
5744
5745         printf("eighth delete on close test succeeded.\n");
5746
5747         /* Test 9 ... */
5748
5749         /* This should fail - we need to set DELETE_ACCESS. */
5750         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5751                               FILE_ATTRIBUTE_NORMAL,
5752                               FILE_SHARE_NONE,
5753                               FILE_OVERWRITE_IF,
5754                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5755         if (NT_STATUS_IS_OK(status)) {
5756                 printf("[9] open of %s succeeded should have failed!\n", fname);
5757                 goto fail;
5758         }
5759
5760         printf("ninth delete on close test succeeded.\n");
5761
5762         /* Test 10 ... */
5763
5764         status = cli_ntcreate(cli1, fname, 0,
5765                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5766                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5767                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5768                              0, &fnum1, NULL);
5769         if (!NT_STATUS_IS_OK(status)) {
5770                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5771                 goto fail;
5772         }
5773
5774         /* This should delete the file. */
5775         status = cli_close(cli1, fnum1);
5776         if (!NT_STATUS_IS_OK(status)) {
5777                 printf("[10] close failed (%s)\n", nt_errstr(status));
5778                 goto fail;
5779         }
5780
5781         /* This should fail.. */
5782         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5783         if (NT_STATUS_IS_OK(status)) {
5784                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5785                 goto fail;
5786         }
5787
5788         printf("tenth delete on close test succeeded.\n");
5789
5790         /* Test 11 ... */
5791
5792         cli_setatr(cli1, fname, 0, 0);
5793         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5794
5795         /* Can we open a read-only file with delete access? */
5796
5797         /* Create a readonly file. */
5798         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5799                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5800                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5801         if (!NT_STATUS_IS_OK(status)) {
5802                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5803                 goto fail;
5804         }
5805
5806         status = cli_close(cli1, fnum1);
5807         if (!NT_STATUS_IS_OK(status)) {
5808                 printf("[11] close failed (%s)\n", nt_errstr(status));
5809                 goto fail;
5810         }
5811
5812         /* Now try open for delete access. */
5813         status = cli_ntcreate(cli1, fname, 0,
5814                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5815                              0,
5816                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5817                              FILE_OPEN, 0, 0, &fnum1, NULL);
5818         if (!NT_STATUS_IS_OK(status)) {
5819                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5820                 goto fail;
5821         }
5822
5823         cli_close(cli1, fnum1);
5824
5825         printf("eleventh delete on close test succeeded.\n");
5826
5827         /*
5828          * Test 12
5829          * like test 4 but with initial delete on close
5830          */
5831
5832         cli_setatr(cli1, fname, 0, 0);
5833         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5834
5835         status = cli_ntcreate(cli1, fname, 0,
5836                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5837                               FILE_ATTRIBUTE_NORMAL,
5838                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5839                               FILE_OVERWRITE_IF,
5840                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5841         if (!NT_STATUS_IS_OK(status)) {
5842                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5843                 goto fail;
5844         }
5845
5846         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5847                               FILE_ATTRIBUTE_NORMAL,
5848                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5849                               FILE_OPEN, 0, 0, &fnum2, NULL);
5850         if (!NT_STATUS_IS_OK(status)) {
5851                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5852                 goto fail;
5853         }
5854
5855         status = cli_close(cli1, fnum2);
5856         if (!NT_STATUS_IS_OK(status)) {
5857                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5858                 goto fail;
5859         }
5860
5861         status = cli_nt_delete_on_close(cli1, fnum1, true);
5862         if (!NT_STATUS_IS_OK(status)) {
5863                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5864                 goto fail;
5865         }
5866
5867         /* This should fail - no more opens once delete on close set. */
5868         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5869                               FILE_ATTRIBUTE_NORMAL,
5870                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5871                               FILE_OPEN, 0, 0, &fnum2, NULL);
5872         if (NT_STATUS_IS_OK(status)) {
5873                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5874                 goto fail;
5875         }
5876
5877         status = cli_nt_delete_on_close(cli1, fnum1, false);
5878         if (!NT_STATUS_IS_OK(status)) {
5879                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5880                 goto fail;
5881         }
5882
5883         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5884                               FILE_ATTRIBUTE_NORMAL,
5885                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5886                               FILE_OPEN, 0, 0, &fnum2, NULL);
5887         if (!NT_STATUS_IS_OK(status)) {
5888                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5889                 goto fail;
5890         }
5891
5892         status = cli_close(cli1, fnum2);
5893         if (!NT_STATUS_IS_OK(status)) {
5894                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5895                 goto fail;
5896         }
5897
5898         status = cli_close(cli1, fnum1);
5899         if (!NT_STATUS_IS_OK(status)) {
5900                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5901                 goto fail;
5902         }
5903
5904         /*
5905          * setting delete on close on the handle does
5906          * not unset the initial delete on close...
5907          */
5908         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5909                               FILE_ATTRIBUTE_NORMAL,
5910                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5911                               FILE_OPEN, 0, 0, &fnum2, NULL);
5912         if (NT_STATUS_IS_OK(status)) {
5913                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5914                 goto fail;
5915         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5916                 printf("ntcreate returned %s, expected "
5917                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5918                        nt_errstr(status));
5919                 goto fail;
5920         }
5921
5922         printf("twelfth delete on close test succeeded.\n");
5923
5924
5925         printf("finished delete test\n");
5926
5927         correct = true;
5928
5929   fail:
5930         /* FIXME: This will crash if we aborted before cli2 got
5931          * initialized, because these functions don't handle
5932          * uninitialized connections. */
5933
5934         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5935         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5936         cli_setatr(cli1, fname, 0, 0);
5937         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5938
5939         if (cli1 && !torture_close_connection(cli1)) {
5940                 correct = False;
5941         }
5942         if (cli2 && !torture_close_connection(cli2)) {
5943                 correct = False;
5944         }
5945         return correct;
5946 }
5947
5948 struct delete_stream_state {
5949         bool closed;
5950 };
5951
5952 static void delete_stream_unlinked(struct tevent_req *subreq);
5953 static void delete_stream_closed(struct tevent_req *subreq);
5954
5955 static struct tevent_req *delete_stream_send(
5956         TALLOC_CTX *mem_ctx,
5957         struct tevent_context *ev,
5958         struct cli_state *cli,
5959         const char *base_fname,
5960         uint16_t stream_fnum)
5961 {
5962         struct tevent_req *req = NULL, *subreq = NULL;
5963         struct delete_stream_state *state = NULL;
5964
5965         req = tevent_req_create(
5966                 mem_ctx, &state, struct delete_stream_state);
5967         if (req == NULL) {
5968                 return NULL;
5969         }
5970
5971         subreq = cli_unlink_send(
5972                 state,
5973                 ev,
5974                 cli,
5975                 base_fname,
5976                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5977         if (tevent_req_nomem(subreq, req)) {
5978                 return tevent_req_post(req, ev);
5979         }
5980         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5981
5982         subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5983         if (tevent_req_nomem(subreq, req)) {
5984                 return tevent_req_post(req, ev);
5985         }
5986         tevent_req_set_callback(subreq, delete_stream_closed, req);
5987
5988         return req;
5989 }
5990
5991 static void delete_stream_unlinked(struct tevent_req *subreq)
5992 {
5993         struct tevent_req *req = tevent_req_callback_data(
5994                 subreq, struct tevent_req);
5995         struct delete_stream_state *state = tevent_req_data(
5996                 req, struct delete_stream_state);
5997         NTSTATUS status;
5998
5999         status = cli_unlink_recv(subreq);
6000         TALLOC_FREE(subreq);
6001         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6002                 printf("cli_unlink returned %s\n",
6003                        nt_errstr(status));
6004                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6005                 return;
6006         }
6007         if (!state->closed) {
6008                 /* close reply should have come in first */
6009                 printf("Not closed\n");
6010                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6011                 return;
6012         }
6013         tevent_req_done(req);
6014 }
6015
6016 static void delete_stream_closed(struct tevent_req *subreq)
6017 {
6018         struct tevent_req *req = tevent_req_callback_data(
6019                 subreq, struct tevent_req);
6020         struct delete_stream_state *state = tevent_req_data(
6021                 req, struct delete_stream_state);
6022         NTSTATUS status;
6023
6024         status = cli_close_recv(subreq);
6025         TALLOC_FREE(subreq);
6026         if (tevent_req_nterror(req, status)) {
6027                 return;
6028         }
6029         /* also waiting for the unlink to come back */
6030         state->closed = true;
6031 }
6032
6033 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6034 {
6035         return tevent_req_simple_recv_ntstatus(req);
6036 }
6037
6038 static bool run_delete_stream(int dummy)
6039 {
6040         struct tevent_context *ev = NULL;
6041         struct tevent_req *req = NULL;
6042         struct cli_state *cli = NULL;
6043         const char fname[] = "delete_stream";
6044         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6045         uint16_t fnum1, fnum2;
6046         NTSTATUS status;
6047         bool ok;
6048
6049         printf("Starting stream delete test\n");
6050
6051         ok = torture_open_connection(&cli, 0);
6052         if (!ok) {
6053                 return false;
6054         }
6055
6056         cli_setatr(cli, fname, 0, 0);
6057         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6058
6059         /* Create the file. */
6060         status = cli_ntcreate(
6061                 cli,
6062                 fname,
6063                 0,
6064                 READ_CONTROL_ACCESS,
6065                 0,
6066                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6067                 FILE_CREATE,
6068                 0x0,
6069                 0x0,
6070                 &fnum1,
6071                 NULL);
6072         if (!NT_STATUS_IS_OK(status)) {
6073                 d_fprintf(stderr,
6074                           "cli_ntcreate of %s failed (%s)\n",
6075                           fname,
6076                           nt_errstr(status));
6077                 return false;
6078         }
6079         status = cli_close(cli, fnum1);
6080         if (!NT_STATUS_IS_OK(status)) {
6081                 d_fprintf(stderr,
6082                           "cli_close of %s failed (%s)\n",
6083                           fname,
6084                           nt_errstr(status));
6085                 return false;
6086         }
6087
6088         /* Now create the stream. */
6089         status = cli_ntcreate(
6090                 cli,
6091                 fname_stream,
6092                 0,
6093                 FILE_WRITE_DATA,
6094                 0,
6095                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6096                 FILE_CREATE,
6097                 0x0,
6098                 0x0,
6099                 &fnum1,
6100                 NULL);
6101
6102         if (!NT_STATUS_IS_OK(status)) {
6103                 d_fprintf(stderr,
6104                           "cli_ntcreate of %s failed (%s)\n",
6105                           fname_stream,
6106                           nt_errstr(status));
6107                 return false;
6108         }
6109
6110         /* open it a second time */
6111
6112         status = cli_ntcreate(
6113                 cli,
6114                 fname_stream,
6115                 0,
6116                 FILE_WRITE_DATA,
6117                 0,
6118                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6119                 FILE_OPEN,
6120                 0x0,
6121                 0x0,
6122                 &fnum2,
6123                 NULL);
6124
6125         if (!NT_STATUS_IS_OK(status)) {
6126                 d_fprintf(stderr,
6127                           "2nd cli_ntcreate of %s failed (%s)\n",
6128                           fname_stream,
6129                           nt_errstr(status));
6130                 return false;
6131         }
6132
6133         ev = samba_tevent_context_init(talloc_tos());
6134         if (ev == NULL) {
6135                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6136                 return false;
6137         }
6138
6139         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6140         if (req == NULL) {
6141                 d_fprintf(stderr, "delete_stream_send failed\n");
6142                 return false;
6143         }
6144
6145         ok = tevent_req_poll_ntstatus(req, ev, &status);
6146         if (!ok) {
6147                 d_fprintf(stderr,
6148                           "tevent_req_poll_ntstatus failed: %s\n",
6149                           nt_errstr(status));
6150                 return false;
6151         }
6152
6153         status = delete_stream_recv(req);
6154         TALLOC_FREE(req);
6155         if (!NT_STATUS_IS_OK(status)) {
6156                 d_fprintf(stderr,
6157                           "delete_stream failed: %s\n",
6158                           nt_errstr(status));
6159                 return false;
6160         }
6161
6162         status = cli_close(cli, fnum2);
6163         if (!NT_STATUS_IS_OK(status)) {
6164                 d_fprintf(stderr,
6165                           "close failed: %s\n",
6166                           nt_errstr(status));
6167                 return false;
6168         }
6169
6170         status = cli_unlink(
6171                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6172         if (!NT_STATUS_IS_OK(status)) {
6173                 d_fprintf(stderr,
6174                           "unlink failed: %s\n",
6175                           nt_errstr(status));
6176                 return false;
6177         }
6178
6179         return true;
6180 }
6181
6182 /*
6183   Exercise delete on close semantics - use on the PRINT1 share in torture
6184   testing.
6185  */
6186 static bool run_delete_print_test(int dummy)
6187 {
6188         struct cli_state *cli1 = NULL;
6189         const char *fname = "print_delete.file";
6190         uint16_t fnum1 = (uint16_t)-1;
6191         bool correct = false;
6192         const char *buf = "print file data\n";
6193         NTSTATUS status;
6194
6195         printf("starting print delete test\n");
6196
6197         if (!torture_open_connection(&cli1, 0)) {
6198                 return false;
6199         }
6200
6201         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6202
6203         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6204                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6205                               0, 0, &fnum1, NULL);
6206         if (!NT_STATUS_IS_OK(status)) {
6207                 printf("open of %s failed (%s)\n",
6208                         fname,
6209                         nt_errstr(status));
6210                 goto fail;
6211         }
6212
6213         status = cli_writeall(cli1,
6214                         fnum1,
6215                         0,
6216                         (const uint8_t *)buf,
6217                         0, /* offset */
6218                         strlen(buf), /* size */
6219                         NULL);
6220         if (!NT_STATUS_IS_OK(status)) {
6221                 printf("writing print file data failed (%s)\n",
6222                         nt_errstr(status));
6223                 goto fail;
6224         }
6225
6226         status = cli_nt_delete_on_close(cli1, fnum1, true);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 printf("setting delete_on_close failed (%s)\n",
6229                         nt_errstr(status));
6230                 goto fail;
6231         }
6232
6233         status = cli_close(cli1, fnum1);
6234         if (!NT_STATUS_IS_OK(status)) {
6235                 printf("close failed (%s)\n", nt_errstr(status));
6236                 goto fail;
6237         }
6238
6239         printf("finished print delete test\n");
6240
6241         correct = true;
6242
6243   fail:
6244
6245         if (fnum1 != (uint16_t)-1) {
6246                 cli_close(cli1, fnum1);
6247         }
6248
6249         if (cli1 && !torture_close_connection(cli1)) {
6250                 correct = false;
6251         }
6252         return correct;
6253 }
6254
6255 static bool run_deletetest_ln(int dummy)
6256 {
6257         struct cli_state *cli;
6258         const char *fname = "\\delete1";
6259         const char *fname_ln = "\\delete1_ln";
6260         uint16_t fnum;
6261         uint16_t fnum1;
6262         NTSTATUS status;
6263         bool correct = true;
6264         time_t t;
6265
6266         printf("starting deletetest-ln\n");
6267
6268         if (!torture_open_connection(&cli, 0)) {
6269                 return false;
6270         }
6271
6272         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6273         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6274
6275         smbXcli_conn_set_sockopt(cli->conn, sockops);
6276
6277         /* Create the file. */
6278         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6279         if (!NT_STATUS_IS_OK(status)) {
6280                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6281                 return false;
6282         }
6283
6284         status = cli_close(cli, fnum);
6285         if (!NT_STATUS_IS_OK(status)) {
6286                 printf("close1 failed (%s)\n", nt_errstr(status));
6287                 return false;
6288         }
6289
6290         /* Now create a hardlink. */
6291         status = cli_hardlink(cli, fname, fname_ln);
6292         if (!NT_STATUS_IS_OK(status)) {
6293                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6294                 return false;
6295         }
6296
6297         /* Open the original file. */
6298         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6299                         FILE_ATTRIBUTE_NORMAL,
6300                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6301                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6302         if (!NT_STATUS_IS_OK(status)) {
6303                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6304                 return false;
6305         }
6306
6307         /* Unlink the hard link path. */
6308         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6309                         FILE_ATTRIBUTE_NORMAL,
6310                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6311                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6312         if (!NT_STATUS_IS_OK(status)) {
6313                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6314                 return false;
6315         }
6316         status = cli_nt_delete_on_close(cli, fnum1, true);
6317         if (!NT_STATUS_IS_OK(status)) {
6318                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6319                         __location__, fname_ln, nt_errstr(status));
6320                 return false;
6321         }
6322
6323         status = cli_close(cli, fnum1);
6324         if (!NT_STATUS_IS_OK(status)) {
6325                 printf("close %s failed (%s)\n",
6326                         fname_ln, nt_errstr(status));
6327                 return false;
6328         }
6329
6330         status = cli_close(cli, fnum);
6331         if (!NT_STATUS_IS_OK(status)) {
6332                 printf("close %s failed (%s)\n",
6333                         fname, nt_errstr(status));
6334                 return false;
6335         }
6336
6337         /* Ensure the original file is still there. */
6338         status = cli_getatr(cli, fname, NULL, NULL, &t);
6339         if (!NT_STATUS_IS_OK(status)) {
6340                 printf("%s getatr on file %s failed (%s)\n",
6341                         __location__,
6342                         fname,
6343                         nt_errstr(status));
6344                 correct = False;
6345         }
6346
6347         /* Ensure the link path is gone. */
6348         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6349         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6350                 printf("%s, getatr for file %s returned wrong error code %s "
6351                         "- should have been deleted\n",
6352                         __location__,
6353                         fname_ln, nt_errstr(status));
6354                 correct = False;
6355         }
6356
6357         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6358         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6359
6360         if (!torture_close_connection(cli)) {
6361                 correct = false;
6362         }
6363
6364         printf("finished deletetest-ln\n");
6365
6366         return correct;
6367 }
6368
6369 /*
6370   print out server properties
6371  */
6372 static bool run_properties(int dummy)
6373 {
6374         struct cli_state *cli;
6375         bool correct = True;
6376
6377         printf("starting properties test\n");
6378
6379         ZERO_STRUCT(cli);
6380
6381         if (!torture_open_connection(&cli, 0)) {
6382                 return False;
6383         }
6384
6385         smbXcli_conn_set_sockopt(cli->conn, sockops);
6386
6387         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6388
6389         if (!torture_close_connection(cli)) {
6390                 correct = False;
6391         }
6392
6393         return correct;
6394 }
6395
6396
6397
6398 /* FIRST_DESIRED_ACCESS   0xf019f */
6399 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6400                                FILE_READ_EA|                           /* 0xf */ \
6401                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6402                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6403                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6404                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6405 /* SECOND_DESIRED_ACCESS  0xe0080 */
6406 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6407                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6408                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6409
6410 #if 0
6411 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6412                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6413                                FILE_READ_DATA|\
6414                                WRITE_OWNER_ACCESS                      /* */
6415 #endif
6416
6417 /*
6418   Test ntcreate calls made by xcopy
6419  */
6420 static bool run_xcopy(int dummy)
6421 {
6422         static struct cli_state *cli1;
6423         const char *fname = "\\test.txt";
6424         bool correct = True;
6425         uint16_t fnum1, fnum2;
6426         NTSTATUS status;
6427
6428         printf("starting xcopy test\n");
6429
6430         if (!torture_open_connection(&cli1, 0)) {
6431                 return False;
6432         }
6433
6434         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6435                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6436                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6437         if (!NT_STATUS_IS_OK(status)) {
6438                 printf("First open failed - %s\n", nt_errstr(status));
6439                 return False;
6440         }
6441
6442         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6443                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6444                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6445         if (!NT_STATUS_IS_OK(status)) {
6446                 printf("second open failed - %s\n", nt_errstr(status));
6447                 return False;
6448         }
6449
6450         if (!torture_close_connection(cli1)) {
6451                 correct = False;
6452         }
6453
6454         return correct;
6455 }
6456
6457 /*
6458   Test rename on files open with share delete and no share delete.
6459  */
6460 static bool run_rename(int dummy)
6461 {
6462         static struct cli_state *cli1;
6463         const char *fname = "\\test.txt";
6464         const char *fname1 = "\\test1.txt";
6465         bool correct = True;
6466         uint16_t fnum1;
6467         uint32_t attr;
6468         NTSTATUS status;
6469
6470         printf("starting rename test\n");
6471
6472         if (!torture_open_connection(&cli1, 0)) {
6473                 return False;
6474         }
6475
6476         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6477         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6478
6479         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6480                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6481                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6482         if (!NT_STATUS_IS_OK(status)) {
6483                 printf("First open failed - %s\n", nt_errstr(status));
6484                 return False;
6485         }
6486
6487         status = cli_rename(cli1, fname, fname1, false);
6488         if (!NT_STATUS_IS_OK(status)) {
6489                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6490         } else {
6491                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6492                 correct = False;
6493         }
6494
6495         status = cli_close(cli1, fnum1);
6496         if (!NT_STATUS_IS_OK(status)) {
6497                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6498                 return False;
6499         }
6500
6501         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6502         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6503         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6504 #if 0
6505                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6506 #else
6507                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6508 #endif
6509                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6510         if (!NT_STATUS_IS_OK(status)) {
6511                 printf("Second open failed - %s\n", nt_errstr(status));
6512                 return False;
6513         }
6514
6515         status = cli_rename(cli1, fname, fname1, false);
6516         if (!NT_STATUS_IS_OK(status)) {
6517                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6518                 correct = False;
6519         } else {
6520                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6521         }
6522
6523         status = cli_close(cli1, fnum1);
6524         if (!NT_STATUS_IS_OK(status)) {
6525                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6526                 return False;
6527         }
6528
6529         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6530         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6531
6532         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6533                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6534                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6535         if (!NT_STATUS_IS_OK(status)) {
6536                 printf("Third open failed - %s\n", nt_errstr(status));
6537                 return False;
6538         }
6539
6540
6541         status = cli_rename(cli1, fname, fname1, false);
6542         if (!NT_STATUS_IS_OK(status)) {
6543                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6544                 correct = False;
6545         } else {
6546                 printf("Third rename succeeded (SHARE_NONE)\n");
6547         }
6548
6549         status = cli_close(cli1, fnum1);
6550         if (!NT_STATUS_IS_OK(status)) {
6551                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6552                 return False;
6553         }
6554
6555         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6556         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6557
6558         /*----*/
6559
6560         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6561                               FILE_ATTRIBUTE_NORMAL,
6562                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6563                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6564         if (!NT_STATUS_IS_OK(status)) {
6565                 printf("Fourth open failed - %s\n", nt_errstr(status));
6566                 return False;
6567         }
6568
6569         status = cli_rename(cli1, fname, fname1, false);
6570         if (!NT_STATUS_IS_OK(status)) {
6571                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6572         } else {
6573                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6574                 correct = False;
6575         }
6576
6577         status = cli_close(cli1, fnum1);
6578         if (!NT_STATUS_IS_OK(status)) {
6579                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6580                 return False;
6581         }
6582
6583         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6584         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6585
6586         /*--*/
6587
6588         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6589                          FILE_ATTRIBUTE_NORMAL,
6590                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6591                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6592         if (!NT_STATUS_IS_OK(status)) {
6593                 printf("Fifth open failed - %s\n", nt_errstr(status));
6594                 return False;
6595         }
6596
6597         status = cli_rename(cli1, fname, fname1, false);
6598         if (!NT_STATUS_IS_OK(status)) {
6599                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6600                 correct = False;
6601         } else {
6602                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6603         }
6604
6605         /*--*/
6606         status = cli_close(cli1, fnum1);
6607         if (!NT_STATUS_IS_OK(status)) {
6608                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6609                 return False;
6610         }
6611
6612         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6613         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6614         if (!NT_STATUS_IS_OK(status)) {
6615                 printf("getatr on file %s failed - %s ! \n",
6616                         fname1, nt_errstr(status));
6617                 correct = False;
6618         } else {
6619                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6620                         printf("Renamed file %s has wrong attr 0x%x "
6621                                 "(should be 0x%x)\n",
6622                                 fname1,
6623                                 attr,
6624                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6625                         correct = False;
6626                 } else {
6627                         printf("Renamed file %s has archive bit set\n", fname1);
6628                 }
6629         }
6630
6631         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6632         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6633
6634         if (!torture_close_connection(cli1)) {
6635                 correct = False;
6636         }
6637
6638         return correct;
6639 }
6640
6641 /*
6642   Test rename into a directory with an ACL denying it.
6643  */
6644 static bool run_rename_access(int dummy)
6645 {
6646         static struct cli_state *cli = NULL;
6647         static struct cli_state *posix_cli = NULL;
6648         const char *src = "test.txt";
6649         const char *dname = "dir";
6650         const char *dst = "dir\\test.txt";
6651         const char *dsrc = "test.dir";
6652         const char *ddst = "dir\\test.dir";
6653         uint16_t fnum = (uint16_t)-1;
6654         struct security_descriptor *sd = NULL;
6655         struct security_descriptor *newsd = NULL;
6656         NTSTATUS status;
6657         TALLOC_CTX *frame = NULL;
6658
6659         frame = talloc_stackframe();
6660         printf("starting rename access test\n");
6661
6662         /* Windows connection. */
6663         if (!torture_open_connection(&cli, 0)) {
6664                 goto fail;
6665         }
6666
6667         smbXcli_conn_set_sockopt(cli->conn, sockops);
6668
6669         /* Posix connection. */
6670         if (!torture_open_connection(&posix_cli, 0)) {
6671                 goto fail;
6672         }
6673
6674         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6675
6676         status = torture_setup_unix_extensions(posix_cli);
6677         if (!NT_STATUS_IS_OK(status)) {
6678                 goto fail;
6679         }
6680
6681         /* Start with a clean slate. */
6682         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6683         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6684         cli_rmdir(cli, dsrc);
6685         cli_rmdir(cli, ddst);
6686         cli_rmdir(cli, dname);
6687
6688         /*
6689          * Setup the destination directory with a DENY ACE to
6690          * prevent new files within it.
6691          */
6692         status = cli_ntcreate(cli,
6693                                 dname,
6694                                 0,
6695                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6696                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6697                                         WRITE_OWNER_ACCESS,
6698                                 FILE_ATTRIBUTE_DIRECTORY,
6699                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6700                                 FILE_CREATE,
6701                                 FILE_DIRECTORY_FILE,
6702                                 0,
6703                                 &fnum,
6704                                 NULL);
6705         if (!NT_STATUS_IS_OK(status)) {
6706                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6707                 goto fail;
6708         }
6709
6710         status = cli_query_secdesc(cli,
6711                                 fnum,
6712                                 frame,
6713                                 &sd);
6714         if (!NT_STATUS_IS_OK(status)) {
6715                 printf("cli_query_secdesc failed for %s (%s)\n",
6716                         dname, nt_errstr(status));
6717                 goto fail;
6718         }
6719
6720         newsd = security_descriptor_dacl_create(frame,
6721                                         0,
6722                                         NULL,
6723                                         NULL,
6724                                         SID_WORLD,
6725                                         SEC_ACE_TYPE_ACCESS_DENIED,
6726                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6727                                         0,
6728                                         NULL);
6729         if (newsd == NULL) {
6730                 goto fail;
6731         }
6732         sd->dacl = security_acl_concatenate(frame,
6733                                         newsd->dacl,
6734                                         sd->dacl);
6735         if (sd->dacl == NULL) {
6736                 goto fail;
6737         }
6738         status = cli_set_secdesc(cli, fnum, sd);
6739         if (!NT_STATUS_IS_OK(status)) {
6740                 printf("cli_set_secdesc failed for %s (%s)\n",
6741                         dname, nt_errstr(status));
6742                 goto fail;
6743         }
6744         status = cli_close(cli, fnum);
6745         if (!NT_STATUS_IS_OK(status)) {
6746                 printf("close failed for %s (%s)\n",
6747                         dname, nt_errstr(status));
6748                 goto fail;
6749         }
6750         /* Now go around the back and chmod to 777 via POSIX. */
6751         status = cli_posix_chmod(posix_cli, dname, 0777);
6752         if (!NT_STATUS_IS_OK(status)) {
6753                 printf("cli_posix_chmod failed for %s (%s)\n",
6754                         dname, nt_errstr(status));
6755                 goto fail;
6756         }
6757
6758         /* Check we can't create a file within dname via Windows. */
6759         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6760         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6761                 cli_close(posix_cli, fnum);
6762                 printf("Create of %s should be ACCESS denied, was %s\n",
6763                         dst, nt_errstr(status));
6764                 goto fail;
6765         }
6766
6767         /* Make the sample file/directory. */
6768         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6769         if (!NT_STATUS_IS_OK(status)) {
6770                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6771                 goto fail;
6772         }
6773         status = cli_close(cli, fnum);
6774         if (!NT_STATUS_IS_OK(status)) {
6775                 printf("cli_close failed (%s)\n", nt_errstr(status));
6776                 goto fail;
6777         }
6778
6779         status = cli_mkdir(cli, dsrc);
6780         if (!NT_STATUS_IS_OK(status)) {
6781                 printf("cli_mkdir of %s failed (%s)\n",
6782                         dsrc, nt_errstr(status));
6783                 goto fail;
6784         }
6785
6786         /*
6787          * OK - renames of the new file and directory into the
6788          * dst directory should fail.
6789          */
6790
6791         status = cli_rename(cli, src, dst, false);
6792         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6793                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6794                         src, dst, nt_errstr(status));
6795                 goto fail;
6796         }
6797         status = cli_rename(cli, dsrc, ddst, false);
6798         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6799                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6800                         src, dst, nt_errstr(status));
6801                 goto fail;
6802         }
6803
6804         TALLOC_FREE(frame);
6805         return true;
6806
6807   fail:
6808
6809         if (posix_cli) {
6810                 torture_close_connection(posix_cli);
6811         }
6812
6813         if (cli) {
6814                 if (fnum != (uint16_t)-1) {
6815                         cli_close(cli, fnum);
6816                 }
6817                 cli_unlink(cli, src,
6818                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6819                 cli_unlink(cli, dst,
6820                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6821                 cli_rmdir(cli, dsrc);
6822                 cli_rmdir(cli, ddst);
6823                 cli_rmdir(cli, dname);
6824
6825                 torture_close_connection(cli);
6826         }
6827
6828         TALLOC_FREE(frame);
6829         return false;
6830 }
6831
6832 /*
6833   Test owner rights ACE.
6834  */
6835 static bool run_owner_rights(int dummy)
6836 {
6837         static struct cli_state *cli = NULL;
6838         const char *fname = "owner_rights.txt";
6839         uint16_t fnum = (uint16_t)-1;
6840         struct security_descriptor *sd = NULL;
6841         struct security_descriptor *newsd = NULL;
6842         NTSTATUS status;
6843         TALLOC_CTX *frame = NULL;
6844
6845         frame = talloc_stackframe();
6846         printf("starting owner rights test\n");
6847
6848         /* Windows connection. */
6849         if (!torture_open_connection(&cli, 0)) {
6850                 goto fail;
6851         }
6852
6853         smbXcli_conn_set_sockopt(cli->conn, sockops);
6854
6855         /* Start with a clean slate. */
6856         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6857
6858         /* Create the test file. */
6859         /* Now try and open for read and write-dac. */
6860         status = cli_ntcreate(cli,
6861                                 fname,
6862                                 0,
6863                                 GENERIC_ALL_ACCESS,
6864                                 FILE_ATTRIBUTE_NORMAL,
6865                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6866                                         FILE_SHARE_DELETE,
6867                                 FILE_CREATE,
6868                                 0,
6869                                 0,
6870                                 &fnum,
6871                                 NULL);
6872         if (!NT_STATUS_IS_OK(status)) {
6873                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6874                 goto fail;
6875         }
6876
6877         /* Get the original SD. */
6878         status = cli_query_secdesc(cli,
6879                                 fnum,
6880                                 frame,
6881                                 &sd);
6882         if (!NT_STATUS_IS_OK(status)) {
6883                 printf("cli_query_secdesc failed for %s (%s)\n",
6884                         fname, nt_errstr(status));
6885                 goto fail;
6886         }
6887
6888         /*
6889          * Add an "owner-rights" ACE denying WRITE_DATA,
6890          * and an "owner-rights" ACE allowing READ_DATA.
6891          */
6892
6893         newsd = security_descriptor_dacl_create(frame,
6894                                         0,
6895                                         NULL,
6896                                         NULL,
6897                                         SID_OWNER_RIGHTS,
6898                                         SEC_ACE_TYPE_ACCESS_DENIED,
6899                                         FILE_WRITE_DATA,
6900                                         0,
6901                                         SID_OWNER_RIGHTS,
6902                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6903                                         FILE_READ_DATA,
6904                                         0,
6905                                         NULL);
6906         if (newsd == NULL) {
6907                 goto fail;
6908         }
6909         sd->dacl = security_acl_concatenate(frame,
6910                                         newsd->dacl,
6911                                         sd->dacl);
6912         if (sd->dacl == NULL) {
6913                 goto fail;
6914         }
6915         status = cli_set_secdesc(cli, fnum, sd);
6916         if (!NT_STATUS_IS_OK(status)) {
6917                 printf("cli_set_secdesc failed for %s (%s)\n",
6918                         fname, nt_errstr(status));
6919                 goto fail;
6920         }
6921         status = cli_close(cli, fnum);
6922         if (!NT_STATUS_IS_OK(status)) {
6923                 printf("close failed for %s (%s)\n",
6924                         fname, nt_errstr(status));
6925                 goto fail;
6926         }
6927         fnum = (uint16_t)-1;
6928
6929         /* Try and open for FILE_WRITE_DATA */
6930         status = cli_ntcreate(cli,
6931                                 fname,
6932                                 0,
6933                                 FILE_WRITE_DATA,
6934                                 FILE_ATTRIBUTE_NORMAL,
6935                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6936                                         FILE_SHARE_DELETE,
6937                                 FILE_OPEN,
6938                                 0,
6939                                 0,
6940                                 &fnum,
6941                                 NULL);
6942         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6943                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6944                 goto fail;
6945         }
6946
6947         /* Now try and open for FILE_READ_DATA */
6948         status = cli_ntcreate(cli,
6949                                 fname,
6950                                 0,
6951                                 FILE_READ_DATA,
6952                                 FILE_ATTRIBUTE_NORMAL,
6953                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6954                                         FILE_SHARE_DELETE,
6955                                 FILE_OPEN,
6956                                 0,
6957                                 0,
6958                                 &fnum,
6959                                 NULL);
6960         if (!NT_STATUS_IS_OK(status)) {
6961                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6962                 goto fail;
6963         }
6964
6965         status = cli_close(cli, fnum);
6966         if (!NT_STATUS_IS_OK(status)) {
6967                 printf("close failed for %s (%s)\n",
6968                         fname, nt_errstr(status));
6969                 goto fail;
6970         }
6971
6972         /* Restore clean slate. */
6973         TALLOC_FREE(sd);
6974         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6975
6976         /* Create the test file. */
6977         status = cli_ntcreate(cli,
6978                                 fname,
6979                                 0,
6980                                 GENERIC_ALL_ACCESS,
6981                                 FILE_ATTRIBUTE_NORMAL,
6982                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6983                                         FILE_SHARE_DELETE,
6984                                 FILE_CREATE,
6985                                 0,
6986                                 0,
6987                                 &fnum,
6988                                 NULL);
6989         if (!NT_STATUS_IS_OK(status)) {
6990                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6991                 goto fail;
6992         }
6993
6994         /* Get the original SD. */
6995         status = cli_query_secdesc(cli,
6996                                 fnum,
6997                                 frame,
6998                                 &sd);
6999         if (!NT_STATUS_IS_OK(status)) {
7000                 printf("cli_query_secdesc failed for %s (%s)\n",
7001                         fname, nt_errstr(status));
7002                 goto fail;
7003         }
7004
7005         /*
7006          * Add an "owner-rights ACE denying WRITE_DATA,
7007          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7008          */
7009
7010         newsd = security_descriptor_dacl_create(frame,
7011                                         0,
7012                                         NULL,
7013                                         NULL,
7014                                         SID_OWNER_RIGHTS,
7015                                         SEC_ACE_TYPE_ACCESS_DENIED,
7016                                         FILE_WRITE_DATA,
7017                                         0,
7018                                         SID_OWNER_RIGHTS,
7019                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7020                                         FILE_READ_DATA|FILE_WRITE_DATA,
7021                                         0,
7022                                         NULL);
7023         if (newsd == NULL) {
7024                 goto fail;
7025         }
7026         sd->dacl = security_acl_concatenate(frame,
7027                                         newsd->dacl,
7028                                         sd->dacl);
7029         if (sd->dacl == NULL) {
7030                 goto fail;
7031         }
7032         status = cli_set_secdesc(cli, fnum, sd);
7033         if (!NT_STATUS_IS_OK(status)) {
7034                 printf("cli_set_secdesc failed for %s (%s)\n",
7035                         fname, nt_errstr(status));
7036                 goto fail;
7037         }
7038         status = cli_close(cli, fnum);
7039         if (!NT_STATUS_IS_OK(status)) {
7040                 printf("close failed for %s (%s)\n",
7041                         fname, nt_errstr(status));
7042                 goto fail;
7043         }
7044         fnum = (uint16_t)-1;
7045
7046         /* Try and open for FILE_WRITE_DATA */
7047         status = cli_ntcreate(cli,
7048                                 fname,
7049                                 0,
7050                                 FILE_WRITE_DATA,
7051                                 FILE_ATTRIBUTE_NORMAL,
7052                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7053                                         FILE_SHARE_DELETE,
7054                                 FILE_OPEN,
7055                                 0,
7056                                 0,
7057                                 &fnum,
7058                                 NULL);
7059         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7060                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7061                 goto fail;
7062         }
7063
7064         /* Now try and open for FILE_READ_DATA */
7065         status = cli_ntcreate(cli,
7066                                 fname,
7067                                 0,
7068                                 FILE_READ_DATA,
7069                                 FILE_ATTRIBUTE_NORMAL,
7070                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7071                                         FILE_SHARE_DELETE,
7072                                 FILE_OPEN,
7073                                 0,
7074                                 0,
7075                                 &fnum,
7076                                 NULL);
7077         if (!NT_STATUS_IS_OK(status)) {
7078                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7079                 goto fail;
7080         }
7081
7082         status = cli_close(cli, fnum);
7083         if (!NT_STATUS_IS_OK(status)) {
7084                 printf("close failed for %s (%s)\n",
7085                         fname, nt_errstr(status));
7086                 goto fail;
7087         }
7088
7089         /* Restore clean slate. */
7090         TALLOC_FREE(sd);
7091         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7092
7093
7094         /* Create the test file. */
7095         status = cli_ntcreate(cli,
7096                                 fname,
7097                                 0,
7098                                 GENERIC_ALL_ACCESS,
7099                                 FILE_ATTRIBUTE_NORMAL,
7100                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7101                                         FILE_SHARE_DELETE,
7102                                 FILE_CREATE,
7103                                 0,
7104                                 0,
7105                                 &fnum,
7106                                 NULL);
7107         if (!NT_STATUS_IS_OK(status)) {
7108                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7109                 goto fail;
7110         }
7111
7112         /* Get the original SD. */
7113         status = cli_query_secdesc(cli,
7114                                 fnum,
7115                                 frame,
7116                                 &sd);
7117         if (!NT_STATUS_IS_OK(status)) {
7118                 printf("cli_query_secdesc failed for %s (%s)\n",
7119                         fname, nt_errstr(status));
7120                 goto fail;
7121         }
7122
7123         /*
7124          * Add an "authenticated users" ACE allowing READ_DATA,
7125          * add an "owner-rights" denying READ_DATA,
7126          * and an "authenticated users" ACE allowing WRITE_DATA.
7127          */
7128
7129         newsd = security_descriptor_dacl_create(frame,
7130                                         0,
7131                                         NULL,
7132                                         NULL,
7133                                         SID_NT_AUTHENTICATED_USERS,
7134                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7135                                         FILE_READ_DATA,
7136                                         0,
7137                                         SID_OWNER_RIGHTS,
7138                                         SEC_ACE_TYPE_ACCESS_DENIED,
7139                                         FILE_READ_DATA,
7140                                         0,
7141                                         SID_NT_AUTHENTICATED_USERS,
7142                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7143                                         FILE_WRITE_DATA,
7144                                         0,
7145                                         NULL);
7146         if (newsd == NULL) {
7147                 printf("newsd == NULL\n");
7148                 goto fail;
7149         }
7150         sd->dacl = security_acl_concatenate(frame,
7151                                         newsd->dacl,
7152                                         sd->dacl);
7153         if (sd->dacl == NULL) {
7154                 printf("sd->dacl == NULL\n");
7155                 goto fail;
7156         }
7157         status = cli_set_secdesc(cli, fnum, sd);
7158         if (!NT_STATUS_IS_OK(status)) {
7159                 printf("cli_set_secdesc failed for %s (%s)\n",
7160                         fname, nt_errstr(status));
7161                 goto fail;
7162         }
7163         status = cli_close(cli, fnum);
7164         if (!NT_STATUS_IS_OK(status)) {
7165                 printf("close failed for %s (%s)\n",
7166                         fname, nt_errstr(status));
7167                 goto fail;
7168         }
7169         fnum = (uint16_t)-1;
7170
7171         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7172         status = cli_ntcreate(cli,
7173                                 fname,
7174                                 0,
7175                                 FILE_READ_DATA|FILE_WRITE_DATA,
7176                                 FILE_ATTRIBUTE_NORMAL,
7177                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7178                                         FILE_SHARE_DELETE,
7179                                 FILE_OPEN,
7180                                 0,
7181                                 0,
7182                                 &fnum,
7183                                 NULL);
7184         if (!NT_STATUS_IS_OK(status)) {
7185                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7186                 goto fail;
7187         }
7188
7189         status = cli_close(cli, fnum);
7190         if (!NT_STATUS_IS_OK(status)) {
7191                 printf("close failed for %s (%s)\n",
7192                         fname, nt_errstr(status));
7193                 goto fail;
7194         }
7195
7196         cli_unlink(cli, fname,
7197                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7198
7199         TALLOC_FREE(frame);
7200         return true;
7201
7202   fail:
7203
7204         if (cli) {
7205                 if (fnum != (uint16_t)-1) {
7206                         cli_close(cli, fnum);
7207                 }
7208                 cli_unlink(cli, fname,
7209                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7210                 torture_close_connection(cli);
7211         }
7212
7213         TALLOC_FREE(frame);
7214         return false;
7215 }
7216
7217 /*
7218  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7219  * Note this test only works with a user with SeSecurityPrivilege set.
7220  *
7221  * NB. This is also tested in samba3.base.createx_access
7222  * but this makes it very explicit what we're looking for.
7223  */
7224 static bool run_smb1_system_security(int dummy)
7225 {
7226         static struct cli_state *cli = NULL;
7227         const char *fname = "system_security.txt";
7228         uint16_t fnum = (uint16_t)-1;
7229         NTSTATUS status;
7230         TALLOC_CTX *frame = NULL;
7231
7232         frame = talloc_stackframe();
7233         printf("starting smb1 system security test\n");
7234
7235         /* SMB1 connection - torture_open_connection() forces this. */
7236         if (!torture_open_connection(&cli, 0)) {
7237                 goto fail;
7238         }
7239
7240         smbXcli_conn_set_sockopt(cli->conn, sockops);
7241
7242         /* Start with a clean slate. */
7243         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7244
7245         /* Create the test file. */
7246         status = cli_ntcreate(cli,
7247                                 fname,
7248                                 0,
7249                                 GENERIC_ALL_ACCESS,
7250                                 FILE_ATTRIBUTE_NORMAL,
7251                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7252                                         FILE_SHARE_DELETE,
7253                                 FILE_CREATE,
7254                                 0,
7255                                 0,
7256                                 &fnum,
7257                                 NULL);
7258         if (!NT_STATUS_IS_OK(status)) {
7259                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7260                 goto fail;
7261         }
7262
7263         status = cli_close(cli, fnum);
7264
7265         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7266         /*
7267          * On SMB1 this succeeds - SMB2 it fails,
7268          * see the SMB2-SACL test.
7269          */
7270         status = cli_ntcreate(cli,
7271                                 fname,
7272                                 0,
7273                                 SEC_FLAG_SYSTEM_SECURITY,
7274                                 FILE_ATTRIBUTE_NORMAL,
7275                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7276                                         FILE_SHARE_DELETE,
7277                                 FILE_OPEN,
7278                                 0,
7279                                 0,
7280                                 &fnum,
7281                                 NULL);
7282         if (!NT_STATUS_IS_OK(status)) {
7283                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7284                 goto fail;
7285         }
7286
7287         status = cli_close(cli, fnum);
7288
7289         cli_unlink(cli, fname,
7290                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7291
7292         torture_close_connection(cli);
7293         TALLOC_FREE(frame);
7294         return true;
7295
7296   fail:
7297
7298         if (cli) {
7299                 if (fnum != (uint16_t)-1) {
7300                         cli_close(cli, fnum);
7301                 }
7302                 cli_unlink(cli, fname,
7303                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7304                 torture_close_connection(cli);
7305         }
7306
7307         TALLOC_FREE(frame);
7308         return false;
7309 }
7310
7311 static bool run_pipe_number(int dummy)
7312 {
7313         struct cli_state *cli1;
7314         const char *pipe_name = "\\SPOOLSS";
7315         uint16_t fnum;
7316         int num_pipes = 0;
7317         NTSTATUS status;
7318
7319         printf("starting pipenumber test\n");
7320         if (!torture_open_connection(&cli1, 0)) {
7321                 return False;
7322         }
7323
7324         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7325         while(1) {
7326                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7327                                       FILE_ATTRIBUTE_NORMAL,
7328                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7329                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7330                 if (!NT_STATUS_IS_OK(status)) {
7331                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7332                         break;
7333                 }
7334                 num_pipes++;
7335                 printf("\r%6d", num_pipes);
7336         }
7337
7338         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7339         torture_close_connection(cli1);
7340         return True;
7341 }
7342
7343 /*
7344   Test open mode returns on read-only files.
7345  */
7346 static bool run_opentest(int dummy)
7347 {
7348         static struct cli_state *cli1;
7349         static struct cli_state *cli2;
7350         const char *fname = "\\readonly.file";
7351         uint16_t fnum1, fnum2;
7352         char buf[20];
7353         off_t fsize;
7354         bool correct = True;
7355         char *tmp_path;
7356         NTSTATUS status;
7357
7358         printf("starting open test\n");
7359
7360         if (!torture_open_connection(&cli1, 0)) {
7361                 return False;
7362         }
7363
7364         cli_setatr(cli1, fname, 0, 0);
7365         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7366
7367         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7368
7369         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7370         if (!NT_STATUS_IS_OK(status)) {
7371                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7372                 return False;
7373         }
7374
7375         status = cli_close(cli1, fnum1);
7376         if (!NT_STATUS_IS_OK(status)) {
7377                 printf("close2 failed (%s)\n", nt_errstr(status));
7378                 return False;
7379         }
7380
7381         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7382         if (!NT_STATUS_IS_OK(status)) {
7383                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7384                 return False;
7385         }
7386
7387         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7388         if (!NT_STATUS_IS_OK(status)) {
7389                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7390                 return False;
7391         }
7392
7393         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7394         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7395
7396         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7397                         NT_STATUS_ACCESS_DENIED)) {
7398                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7399         }
7400
7401         printf("finished open test 1\n");
7402
7403         cli_close(cli1, fnum1);
7404
7405         /* Now try not readonly and ensure ERRbadshare is returned. */
7406
7407         cli_setatr(cli1, fname, 0, 0);
7408
7409         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7410         if (!NT_STATUS_IS_OK(status)) {
7411                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7412                 return False;
7413         }
7414
7415         /* This will fail - but the error should be ERRshare. */
7416         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7417
7418         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7419                         NT_STATUS_SHARING_VIOLATION)) {
7420                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7421         }
7422
7423         status = cli_close(cli1, fnum1);
7424         if (!NT_STATUS_IS_OK(status)) {
7425                 printf("close2 failed (%s)\n", nt_errstr(status));
7426                 return False;
7427         }
7428
7429         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7430
7431         printf("finished open test 2\n");
7432
7433         /* Test truncate open disposition on file opened for read. */
7434         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7435         if (!NT_STATUS_IS_OK(status)) {
7436                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7437                 return False;
7438         }
7439
7440         /* write 20 bytes. */
7441
7442         memset(buf, '\0', 20);
7443
7444         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7445         if (!NT_STATUS_IS_OK(status)) {
7446                 printf("write failed (%s)\n", nt_errstr(status));
7447                 correct = False;
7448         }
7449
7450         status = cli_close(cli1, fnum1);
7451         if (!NT_STATUS_IS_OK(status)) {
7452                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7453                 return False;
7454         }
7455
7456         /* Ensure size == 20. */
7457         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7458         if (!NT_STATUS_IS_OK(status)) {
7459                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7460                 return False;
7461         }
7462
7463         if (fsize != 20) {
7464                 printf("(3) file size != 20\n");
7465                 return False;
7466         }
7467
7468         /* Now test if we can truncate a file opened for readonly. */
7469         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7470         if (!NT_STATUS_IS_OK(status)) {
7471                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7472                 return False;
7473         }
7474
7475         status = cli_close(cli1, fnum1);
7476         if (!NT_STATUS_IS_OK(status)) {
7477                 printf("close2 failed (%s)\n", nt_errstr(status));
7478                 return False;
7479         }
7480
7481         /* Ensure size == 0. */
7482         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7483         if (!NT_STATUS_IS_OK(status)) {
7484                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7485                 return False;
7486         }
7487
7488         if (fsize != 0) {
7489                 printf("(3) file size != 0\n");
7490                 return False;
7491         }
7492         printf("finished open test 3\n");
7493
7494         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7495
7496         printf("Do ctemp tests\n");
7497         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7498         if (!NT_STATUS_IS_OK(status)) {
7499                 printf("ctemp failed (%s)\n", nt_errstr(status));
7500                 return False;
7501         }
7502
7503         printf("ctemp gave path %s\n", tmp_path);
7504         status = cli_close(cli1, fnum1);
7505         if (!NT_STATUS_IS_OK(status)) {
7506                 printf("close of temp failed (%s)\n", nt_errstr(status));
7507         }
7508
7509         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7510         if (!NT_STATUS_IS_OK(status)) {
7511                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7512         }
7513
7514         /* Test the non-io opens... */
7515
7516         if (!torture_open_connection(&cli2, 1)) {
7517                 return False;
7518         }
7519
7520         cli_setatr(cli2, fname, 0, 0);
7521         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7522
7523         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7524
7525         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7526         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7527                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7528                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7529         if (!NT_STATUS_IS_OK(status)) {
7530                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7531                 return False;
7532         }
7533
7534         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7535                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7536                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7537         if (!NT_STATUS_IS_OK(status)) {
7538                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7539                 return False;
7540         }
7541
7542         status = cli_close(cli1, fnum1);
7543         if (!NT_STATUS_IS_OK(status)) {
7544                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7545                 return False;
7546         }
7547
7548         status = cli_close(cli2, fnum2);
7549         if (!NT_STATUS_IS_OK(status)) {
7550                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7551                 return False;
7552         }
7553
7554         printf("non-io open test #1 passed.\n");
7555
7556         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7557
7558         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7559
7560         status = cli_ntcreate(cli1, fname, 0,
7561                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7562                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7563                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7564         if (!NT_STATUS_IS_OK(status)) {
7565                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7566                 return False;
7567         }
7568
7569         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7570                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7571                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7572         if (!NT_STATUS_IS_OK(status)) {
7573                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7574                 return False;
7575         }
7576
7577         status = cli_close(cli1, fnum1);
7578         if (!NT_STATUS_IS_OK(status)) {
7579                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7580                 return False;
7581         }
7582
7583         status = cli_close(cli2, fnum2);
7584         if (!NT_STATUS_IS_OK(status)) {
7585                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7586                 return False;
7587         }
7588
7589         printf("non-io open test #2 passed.\n");
7590
7591         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7592
7593         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7594
7595         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7596                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7597                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7598         if (!NT_STATUS_IS_OK(status)) {
7599                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7600                 return False;
7601         }
7602
7603         status = cli_ntcreate(cli2, fname, 0,
7604                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7605                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7606                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7607         if (!NT_STATUS_IS_OK(status)) {
7608                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7609                 return False;
7610         }
7611
7612         status = cli_close(cli1, fnum1);
7613         if (!NT_STATUS_IS_OK(status)) {
7614                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7615                 return False;
7616         }
7617
7618         status = cli_close(cli2, fnum2);
7619         if (!NT_STATUS_IS_OK(status)) {
7620                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7621                 return False;
7622         }
7623
7624         printf("non-io open test #3 passed.\n");
7625
7626         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7627
7628         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7629
7630         status = cli_ntcreate(cli1, fname, 0,
7631                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7632                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7633                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7634         if (!NT_STATUS_IS_OK(status)) {
7635                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7636                 return False;
7637         }
7638
7639         status = cli_ntcreate(cli2, fname, 0,
7640                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7641                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7642                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7643         if (NT_STATUS_IS_OK(status)) {
7644                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7645                 return False;
7646         }
7647
7648         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7649
7650         status = cli_close(cli1, fnum1);
7651         if (!NT_STATUS_IS_OK(status)) {
7652                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7653                 return False;
7654         }
7655
7656         printf("non-io open test #4 passed.\n");
7657
7658         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7659
7660         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7661
7662         status = cli_ntcreate(cli1, fname, 0,
7663                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7664                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7665                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7666         if (!NT_STATUS_IS_OK(status)) {
7667                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7668                 return False;
7669         }
7670
7671         status = cli_ntcreate(cli2, fname, 0,
7672                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7673                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7674                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7675         if (!NT_STATUS_IS_OK(status)) {
7676                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7677                 return False;
7678         }
7679
7680         status = cli_close(cli1, fnum1);
7681         if (!NT_STATUS_IS_OK(status)) {
7682                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7683                 return False;
7684         }
7685
7686         status = cli_close(cli2, fnum2);
7687         if (!NT_STATUS_IS_OK(status)) {
7688                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7689                 return False;
7690         }
7691
7692         printf("non-io open test #5 passed.\n");
7693
7694         printf("TEST #6 testing 1 non-io open, one io open\n");
7695
7696         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7697
7698         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7699                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7700                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7701         if (!NT_STATUS_IS_OK(status)) {
7702                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7703                 return False;
7704         }
7705
7706         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7707                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7708                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7709         if (!NT_STATUS_IS_OK(status)) {
7710                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7711                 return False;
7712         }
7713
7714         status = cli_close(cli1, fnum1);
7715         if (!NT_STATUS_IS_OK(status)) {
7716                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7717                 return False;
7718         }
7719
7720         status = cli_close(cli2, fnum2);
7721         if (!NT_STATUS_IS_OK(status)) {
7722                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7723                 return False;
7724         }
7725
7726         printf("non-io open test #6 passed.\n");
7727
7728         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7729
7730         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7731
7732         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7733                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7734                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7735         if (!NT_STATUS_IS_OK(status)) {
7736                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7737                 return False;
7738         }
7739
7740         status = cli_ntcreate(cli2, fname, 0,
7741                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7742                               FILE_ATTRIBUTE_NORMAL,
7743                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7744                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7745         if (NT_STATUS_IS_OK(status)) {
7746                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7747                 return False;
7748         }
7749
7750         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7751
7752         status = cli_close(cli1, fnum1);
7753         if (!NT_STATUS_IS_OK(status)) {
7754                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7755                 return False;
7756         }
7757
7758         printf("non-io open test #7 passed.\n");
7759
7760         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7761
7762         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7763         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7764                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7765                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7766         if (!NT_STATUS_IS_OK(status)) {
7767                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7768                 correct = false;
7769                 goto out;
7770         }
7771
7772         /* Write to ensure we have to update the file time. */
7773         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7774                               NULL);
7775         if (!NT_STATUS_IS_OK(status)) {
7776                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7777                 correct = false;
7778                 goto out;
7779         }
7780
7781         status = cli_close(cli1, fnum1);
7782         if (!NT_STATUS_IS_OK(status)) {
7783                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7784                 correct = false;
7785         }
7786
7787   out:
7788
7789         if (!torture_close_connection(cli1)) {
7790                 correct = False;
7791         }
7792         if (!torture_close_connection(cli2)) {
7793                 correct = False;
7794         }
7795
7796         return correct;
7797 }
7798
7799 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7800 {
7801         uint16_t major, minor;
7802         uint32_t caplow, caphigh;
7803         NTSTATUS status;
7804
7805         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7806                 printf("Server doesn't support UNIX CIFS extensions.\n");
7807                 return NT_STATUS_NOT_SUPPORTED;
7808         }
7809
7810         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7811                                              &caphigh);
7812         if (!NT_STATUS_IS_OK(status)) {
7813                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7814                        nt_errstr(status));
7815                 return status;
7816         }
7817
7818         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7819                                                       caplow, caphigh);
7820         if (!NT_STATUS_IS_OK(status)) {
7821                 printf("Server doesn't support setting UNIX CIFS extensions: "
7822                        "%s.\n", nt_errstr(status));
7823                 return status;
7824         }
7825
7826         return NT_STATUS_OK;
7827 }
7828
7829 /*
7830   Test POSIX open /mkdir calls.
7831  */
7832 static bool run_simple_posix_open_test(int dummy)
7833 {
7834         static struct cli_state *cli1;
7835         const char *fname = "posix:file";
7836         const char *hname = "posix:hlink";
7837         const char *sname = "posix:symlink";
7838         const char *dname = "posix:dir";
7839         char buf[10];
7840         char *target = NULL;
7841         uint16_t fnum1 = (uint16_t)-1;
7842         SMB_STRUCT_STAT sbuf;
7843         bool correct = false;
7844         NTSTATUS status;
7845         size_t nread;
7846         const char *fname_windows = "windows_file";
7847         uint16_t fnum2 = (uint16_t)-1;
7848         bool ok;
7849
7850         printf("Starting simple POSIX open test\n");
7851
7852         if (!torture_open_connection(&cli1, 0)) {
7853                 return false;
7854         }
7855
7856         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7857
7858         status = torture_setup_unix_extensions(cli1);
7859         if (!NT_STATUS_IS_OK(status)) {
7860                 return false;
7861         }
7862
7863         cli_setatr(cli1, fname, 0, 0);
7864         cli_posix_unlink(cli1, fname);
7865         cli_setatr(cli1, dname, 0, 0);
7866         cli_posix_rmdir(cli1, dname);
7867         cli_setatr(cli1, hname, 0, 0);
7868         cli_posix_unlink(cli1, hname);
7869         cli_setatr(cli1, sname, 0, 0);
7870         cli_posix_unlink(cli1, sname);
7871         cli_setatr(cli1, fname_windows, 0, 0);
7872         cli_posix_unlink(cli1, fname_windows);
7873
7874         /* Create a directory. */
7875         status = cli_posix_mkdir(cli1, dname, 0777);
7876         if (!NT_STATUS_IS_OK(status)) {
7877                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7878                 goto out;
7879         }
7880
7881         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7882                                 0600, &fnum1);
7883         if (!NT_STATUS_IS_OK(status)) {
7884                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7885                 goto out;
7886         }
7887
7888         /* Test ftruncate - set file size. */
7889         status = cli_ftruncate(cli1, fnum1, 1000);
7890         if (!NT_STATUS_IS_OK(status)) {
7891                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7892                 goto out;
7893         }
7894
7895         /* Ensure st_size == 1000 */
7896         status = cli_posix_stat(cli1, fname, &sbuf);
7897         if (!NT_STATUS_IS_OK(status)) {
7898                 printf("stat failed (%s)\n", nt_errstr(status));
7899                 goto out;
7900         }
7901
7902         if (sbuf.st_ex_size != 1000) {
7903                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7904                 goto out;
7905         }
7906
7907         /* Ensure st_mode == 0600 */
7908         if ((sbuf.st_ex_mode & 07777) != 0600) {
7909                 printf("posix_open - bad permissions 0%o != 0600\n",
7910                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7911                 goto out;
7912         }
7913
7914         /* Test ftruncate - set file size back to zero. */
7915         status = cli_ftruncate(cli1, fnum1, 0);
7916         if (!NT_STATUS_IS_OK(status)) {
7917                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7918                 goto out;
7919         }
7920
7921         status = cli_close(cli1, fnum1);
7922         if (!NT_STATUS_IS_OK(status)) {
7923                 printf("close failed (%s)\n", nt_errstr(status));
7924                 goto out;
7925         }
7926
7927         /* Now open the file again for read only. */
7928         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7929         if (!NT_STATUS_IS_OK(status)) {
7930                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7931                 goto out;
7932         }
7933
7934         /* Now unlink while open. */
7935         status = cli_posix_unlink(cli1, fname);
7936         if (!NT_STATUS_IS_OK(status)) {
7937                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7938                 goto out;
7939         }
7940
7941         status = cli_close(cli1, fnum1);
7942         if (!NT_STATUS_IS_OK(status)) {
7943                 printf("close(2) failed (%s)\n", nt_errstr(status));
7944                 goto out;
7945         }
7946
7947         /* Ensure the file has gone. */
7948         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7949         if (NT_STATUS_IS_OK(status)) {
7950                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7951                 goto out;
7952         }
7953
7954         /* Create again to test open with O_TRUNC. */
7955         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7956         if (!NT_STATUS_IS_OK(status)) {
7957                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7958                 goto out;
7959         }
7960
7961         /* Test ftruncate - set file size. */
7962         status = cli_ftruncate(cli1, fnum1, 1000);
7963         if (!NT_STATUS_IS_OK(status)) {
7964                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7965                 goto out;
7966         }
7967
7968         /* Ensure st_size == 1000 */
7969         status = cli_posix_stat(cli1, fname, &sbuf);
7970         if (!NT_STATUS_IS_OK(status)) {
7971                 printf("stat failed (%s)\n", nt_errstr(status));
7972                 goto out;
7973         }
7974
7975         if (sbuf.st_ex_size != 1000) {
7976                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7977                 goto out;
7978         }
7979
7980         status = cli_close(cli1, fnum1);
7981         if (!NT_STATUS_IS_OK(status)) {
7982                 printf("close(2) failed (%s)\n", nt_errstr(status));
7983                 goto out;
7984         }
7985
7986         /* Re-open with O_TRUNC. */
7987         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7988         if (!NT_STATUS_IS_OK(status)) {
7989                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7990                 goto out;
7991         }
7992
7993         /* Ensure st_size == 0 */
7994         status = cli_posix_stat(cli1, fname, &sbuf);
7995         if (!NT_STATUS_IS_OK(status)) {
7996                 printf("stat failed (%s)\n", nt_errstr(status));
7997                 goto out;
7998         }
7999
8000         if (sbuf.st_ex_size != 0) {
8001                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
8002                 goto out;
8003         }
8004
8005         status = cli_close(cli1, fnum1);
8006         if (!NT_STATUS_IS_OK(status)) {
8007                 printf("close failed (%s)\n", nt_errstr(status));
8008                 goto out;
8009         }
8010
8011         status = cli_posix_unlink(cli1, fname);
8012         if (!NT_STATUS_IS_OK(status)) {
8013                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8014                 goto out;
8015         }
8016
8017         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8018         if (!NT_STATUS_IS_OK(status)) {
8019                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8020                         dname, nt_errstr(status));
8021                 goto out;
8022         }
8023
8024         cli_close(cli1, fnum1);
8025
8026         /* What happens when we try and POSIX open a directory for write ? */
8027         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8028         if (NT_STATUS_IS_OK(status)) {
8029                 printf("POSIX open of directory %s succeeded, "
8030                        "should have failed.\n",
8031                        dname);
8032                 goto out;
8033         } else {
8034                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8035                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8036                         goto out;
8037                 }
8038         }
8039
8040         /* Create the file. */
8041         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8042                                 0600, &fnum1);
8043         if (!NT_STATUS_IS_OK(status)) {
8044                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8045                 goto out;
8046         }
8047
8048         /* Write some data into it. */
8049         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8050                               NULL);
8051         if (!NT_STATUS_IS_OK(status)) {
8052                 printf("cli_write failed: %s\n", nt_errstr(status));
8053                 goto out;
8054         }
8055
8056         cli_close(cli1, fnum1);
8057
8058         /* Now create a hardlink. */
8059         status = cli_posix_hardlink(cli1, fname, hname);
8060         if (!NT_STATUS_IS_OK(status)) {
8061                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8062                 goto out;
8063         }
8064
8065         /* Now create a symlink. */
8066         status = cli_posix_symlink(cli1, fname, sname);
8067         if (!NT_STATUS_IS_OK(status)) {
8068                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8069                 goto out;
8070         }
8071
8072         /* Open the hardlink for read. */
8073         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8074         if (!NT_STATUS_IS_OK(status)) {
8075                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8076                 goto out;
8077         }
8078
8079         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8080         if (!NT_STATUS_IS_OK(status)) {
8081                 printf("POSIX read of %s failed (%s)\n", hname,
8082                        nt_errstr(status));
8083                 goto out;
8084         } else if (nread != 10) {
8085                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8086                        hname, (unsigned long)nread, 10);
8087                 goto out;
8088         }
8089
8090         if (memcmp(buf, "TEST DATA\n", 10)) {
8091                 printf("invalid data read from hardlink\n");
8092                 goto out;
8093         }
8094
8095         /* Do a POSIX lock/unlock. */
8096         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8097         if (!NT_STATUS_IS_OK(status)) {
8098                 printf("POSIX lock failed %s\n", nt_errstr(status));
8099                 goto out;
8100         }
8101
8102         /* Punch a hole in the locked area. */
8103         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8104         if (!NT_STATUS_IS_OK(status)) {
8105                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8106                 goto out;
8107         }
8108
8109         cli_close(cli1, fnum1);
8110
8111         /* Open the symlink for read - this should fail. A POSIX
8112            client should not be doing opens on a symlink. */
8113         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8114         if (NT_STATUS_IS_OK(status)) {
8115                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8116                 goto out;
8117         }
8118         ok = check_both_error(
8119                 __LINE__, status, ERRDOS, ERRbadpath,
8120                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8121         if (!ok) {
8122                 printf("POSIX open of %s should have failed "
8123                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8124                        "failed with %s instead.\n",
8125                        sname, nt_errstr(status));
8126                 goto out;
8127         }
8128
8129         status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8130         if (!NT_STATUS_IS_OK(status)) {
8131                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8132                 goto out;
8133         }
8134
8135         if (strcmp(target, fname) != 0) {
8136                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8137                         sname, fname, target);
8138                 goto out;
8139         }
8140
8141         status = cli_posix_rmdir(cli1, dname);
8142         if (!NT_STATUS_IS_OK(status)) {
8143                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8144                 goto out;
8145         }
8146
8147         /* Check directory opens with a specific permission. */
8148         status = cli_posix_mkdir(cli1, dname, 0700);
8149         if (!NT_STATUS_IS_OK(status)) {
8150                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8151                 goto out;
8152         }
8153
8154         /* Ensure st_mode == 0700 */
8155         status = cli_posix_stat(cli1, dname, &sbuf);
8156         if (!NT_STATUS_IS_OK(status)) {
8157                 printf("stat failed (%s)\n", nt_errstr(status));
8158                 goto out;
8159         }
8160
8161         if ((sbuf.st_ex_mode & 07777) != 0700) {
8162                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8163                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8164                 goto out;
8165         }
8166
8167         /*
8168          * Now create a Windows file, and attempt a POSIX unlink.
8169          * This should fail with a sharing violation but due to:
8170          *
8171          * [Bug 9571] Unlink after open causes smbd to panic
8172          *
8173          * ensure we've fixed the lock ordering violation.
8174          */
8175
8176         status = cli_ntcreate(cli1, fname_windows, 0,
8177                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8178                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8179                         FILE_CREATE,
8180                         0x0, 0x0, &fnum2, NULL);
8181         if (!NT_STATUS_IS_OK(status)) {
8182                 printf("Windows create of %s failed (%s)\n", fname_windows,
8183                         nt_errstr(status));
8184                 goto out;
8185         }
8186
8187         /* Now try posix_unlink. */
8188         status = cli_posix_unlink(cli1, fname_windows);
8189         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8190                 printf("POSIX unlink of %s should fail "
8191                         "with NT_STATUS_SHARING_VIOLATION "
8192                         "got %s instead !\n",
8193                         fname_windows,
8194                         nt_errstr(status));
8195                 goto out;
8196         }
8197
8198         cli_close(cli1, fnum2);
8199
8200         printf("Simple POSIX open test passed\n");
8201         correct = true;
8202
8203   out:
8204
8205         if (fnum1 != (uint16_t)-1) {
8206                 cli_close(cli1, fnum1);
8207                 fnum1 = (uint16_t)-1;
8208         }
8209
8210         if (fnum2 != (uint16_t)-1) {
8211                 cli_close(cli1, fnum2);
8212                 fnum2 = (uint16_t)-1;
8213         }
8214
8215         cli_setatr(cli1, sname, 0, 0);
8216         cli_posix_unlink(cli1, sname);
8217         cli_setatr(cli1, hname, 0, 0);
8218         cli_posix_unlink(cli1, hname);
8219         cli_setatr(cli1, fname, 0, 0);
8220         cli_posix_unlink(cli1, fname);
8221         cli_setatr(cli1, dname, 0, 0);
8222         cli_posix_rmdir(cli1, dname);
8223         cli_setatr(cli1, fname_windows, 0, 0);
8224         cli_posix_unlink(cli1, fname_windows);
8225
8226         if (!torture_close_connection(cli1)) {
8227                 correct = false;
8228         }
8229
8230         return correct;
8231 }
8232
8233 /*
8234   Test POSIX and Windows ACLs are rejected on symlinks.
8235  */
8236 static bool run_acl_symlink_test(int dummy)
8237 {
8238         static struct cli_state *cli;
8239         const char *fname = "posix_file";
8240         const char *sname = "posix_symlink";
8241         uint16_t fnum = (uint16_t)-1;
8242         bool correct = false;
8243         NTSTATUS status;
8244         char *posix_acl = NULL;
8245         size_t posix_acl_len = 0;
8246         char *posix_acl_sym = NULL;
8247         size_t posix_acl_len_sym = 0;
8248         struct security_descriptor *sd = NULL;
8249         TALLOC_CTX *frame = NULL;
8250
8251         frame = talloc_stackframe();
8252
8253         printf("Starting acl symlink test\n");
8254
8255         if (!torture_open_connection(&cli, 0)) {
8256                 TALLOC_FREE(frame);
8257                 return false;
8258         }
8259
8260         smbXcli_conn_set_sockopt(cli->conn, sockops);
8261
8262         status = torture_setup_unix_extensions(cli);
8263         if (!NT_STATUS_IS_OK(status)) {
8264                 TALLOC_FREE(frame);
8265                 return false;
8266         }
8267
8268         cli_setatr(cli, fname, 0, 0);
8269         cli_posix_unlink(cli, fname);
8270         cli_setatr(cli, sname, 0, 0);
8271         cli_posix_unlink(cli, sname);
8272
8273         status = cli_ntcreate(cli,
8274                         fname,
8275                         0,
8276                         READ_CONTROL_ACCESS,
8277                         0,
8278                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8279                         FILE_CREATE,
8280                         0x0,
8281                         0x0,
8282                         &fnum,
8283                         NULL);
8284
8285         if (!NT_STATUS_IS_OK(status)) {
8286                 printf("cli_ntcreate of %s failed (%s)\n",
8287                         fname,
8288                         nt_errstr(status));
8289                 goto out;
8290         }
8291
8292         /* Get the Windows ACL on the file. */
8293         status = cli_query_secdesc(cli,
8294                                 fnum,
8295                                 frame,
8296                                 &sd);
8297         if (!NT_STATUS_IS_OK(status)) {
8298                 printf("cli_query_secdesc failed (%s)\n",
8299                         nt_errstr(status));
8300                 goto out;
8301         }
8302
8303         /* Get the POSIX ACL on the file. */
8304         status = cli_posix_getacl(cli,
8305                                 fname,
8306                                 frame,
8307                                 &posix_acl_len,
8308                                 &posix_acl);
8309
8310         if (!NT_STATUS_IS_OK(status)) {
8311                 printf("cli_posix_getacl failed (%s)\n",
8312                         nt_errstr(status));
8313                 goto out;
8314         }
8315
8316         status = cli_close(cli, fnum);
8317         if (!NT_STATUS_IS_OK(status)) {
8318                 printf("close failed (%s)\n", nt_errstr(status));
8319                 goto out;
8320         }
8321         fnum = (uint16_t)-1;
8322
8323         /* Now create a symlink. */
8324         status = cli_posix_symlink(cli, fname, sname);
8325         if (!NT_STATUS_IS_OK(status)) {
8326                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8327                         sname,
8328                         fname,
8329                         nt_errstr(status));
8330                 goto out;
8331         }
8332
8333         /* Open a handle on the symlink for SD set/get should fail. */
8334         status = cli_ntcreate(cli,
8335                         sname,
8336                         0,
8337                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8338                         0,
8339                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8340                         FILE_OPEN,
8341                         0x0,
8342                         0x0,
8343                         &fnum,
8344                         NULL);
8345
8346         if (NT_STATUS_IS_OK(status)) {
8347                 printf("Symlink open for getsd/setsd of %s "
8348                         "succeeded (should fail)\n",
8349                         sname);
8350                 goto out;
8351         }
8352
8353         /* Try a stat-open on the symlink, should also fail. */
8354         status = cli_ntcreate(cli,
8355                         sname,
8356                         0,
8357                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8358                         0,
8359                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8360                         FILE_OPEN,
8361                         0x0,
8362                         0x0,
8363                         &fnum,
8364                         NULL);
8365
8366         if (NT_STATUS_IS_OK(status)) {
8367                 printf("Stat-open of symlink succeeded (should fail)\n");
8368                 goto out;
8369         }
8370
8371         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8372         status = cli_posix_getacl(cli,
8373                                 sname,
8374                                 frame,
8375                                 &posix_acl_len_sym,
8376                                 &posix_acl_sym);
8377
8378         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8379                 printf("cli_posix_getacl on a symlink gave %s. "
8380                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8381                         nt_errstr(status));
8382                 goto out;
8383         }
8384
8385         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8386         status = cli_posix_setacl(cli,
8387                                 sname,
8388                                 posix_acl,
8389                                 posix_acl_len);
8390
8391         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8392                 printf("cli_posix_setacl on a symlink gave %s. "
8393                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8394                         nt_errstr(status));
8395                 goto out;
8396         }
8397
8398         printf("ACL symlink test passed\n");
8399         correct = true;
8400
8401   out:
8402
8403         if (fnum != (uint16_t)-1) {
8404                 cli_close(cli, fnum);
8405                 fnum = (uint16_t)-1;
8406         }
8407
8408         cli_setatr(cli, sname, 0, 0);
8409         cli_posix_unlink(cli, sname);
8410         cli_setatr(cli, fname, 0, 0);
8411         cli_posix_unlink(cli, fname);
8412
8413         if (!torture_close_connection(cli)) {
8414                 correct = false;
8415         }
8416
8417         TALLOC_FREE(frame);
8418         return correct;
8419 }
8420
8421 /*
8422   Test POSIX can delete a file containing streams.
8423  */
8424 static bool run_posix_stream_delete(int dummy)
8425 {
8426         struct cli_state *cli1 = NULL;
8427         struct cli_state *cli2 = NULL;
8428         const char *fname = "streamfile";
8429         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8430         uint16_t fnum1 = (uint16_t)-1;
8431         bool correct = false;
8432         NTSTATUS status;
8433         TALLOC_CTX *frame = NULL;
8434
8435         frame = talloc_stackframe();
8436
8437         printf("Starting POSIX stream delete test\n");
8438
8439         if (!torture_open_connection(&cli1, 0) ||
8440                         !torture_open_connection(&cli2, 1)) {
8441                 TALLOC_FREE(frame);
8442                 return false;
8443         }
8444
8445         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8446         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8447
8448         status = torture_setup_unix_extensions(cli2);
8449         if (!NT_STATUS_IS_OK(status)) {
8450                 goto out;
8451         }
8452
8453         cli_setatr(cli1, fname, 0, 0);
8454         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8455
8456         /* Create the file. */
8457         status = cli_ntcreate(cli1,
8458                         fname,
8459                         0,
8460                         READ_CONTROL_ACCESS,
8461                         0,
8462                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8463                         FILE_CREATE,
8464                         0x0,
8465                         0x0,
8466                         &fnum1,
8467                         NULL);
8468
8469         if (!NT_STATUS_IS_OK(status)) {
8470                 printf("cli_ntcreate of %s failed (%s)\n",
8471                         fname,
8472                         nt_errstr(status));
8473                 goto out;
8474         }
8475
8476         status = cli_close(cli1, fnum1);
8477         if (!NT_STATUS_IS_OK(status)) {
8478                 printf("cli_close of %s failed (%s)\n",
8479                         fname,
8480                         nt_errstr(status));
8481                 goto out;
8482         }
8483         fnum1 = (uint16_t)-1;
8484
8485         /* Now create the stream. */
8486         status = cli_ntcreate(cli1,
8487                         stream_fname,
8488                         0,
8489                         FILE_WRITE_DATA,
8490                         0,
8491                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8492                         FILE_CREATE,
8493                         0x0,
8494                         0x0,
8495                         &fnum1,
8496                         NULL);
8497
8498         if (!NT_STATUS_IS_OK(status)) {
8499                 printf("cli_ntcreate of %s failed (%s)\n",
8500                         stream_fname,
8501                         nt_errstr(status));
8502                 goto out;
8503         }
8504
8505         /* Leave the stream handle open... */
8506
8507         /* POSIX unlink should fail. */
8508         status = cli_posix_unlink(cli2, fname);
8509         if (NT_STATUS_IS_OK(status)) {
8510                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8511                         fname);
8512                 goto out;
8513         }
8514
8515         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8516                 printf("cli_posix_unlink of %s failed with (%s) "
8517                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8518                         fname,
8519                         nt_errstr(status));
8520                 goto out;
8521         }
8522
8523         /* Close the stream handle. */
8524         status = cli_close(cli1, fnum1);
8525         if (!NT_STATUS_IS_OK(status)) {
8526                 printf("cli_close of %s failed (%s)\n",
8527                         stream_fname,
8528                         nt_errstr(status));
8529                 goto out;
8530         }
8531         fnum1 = (uint16_t)-1;
8532
8533         /* POSIX unlink after stream handle closed should succeed. */
8534         status = cli_posix_unlink(cli2, fname);
8535         if (!NT_STATUS_IS_OK(status)) {
8536                 printf("cli_posix_unlink of %s failed (%s)\n",
8537                         fname,
8538                         nt_errstr(status));
8539                 goto out;
8540         }
8541
8542         printf("POSIX stream delete test passed\n");
8543         correct = true;
8544
8545   out:
8546
8547         if (fnum1 != (uint16_t)-1) {
8548                 cli_close(cli1, fnum1);
8549                 fnum1 = (uint16_t)-1;
8550         }
8551
8552         cli_setatr(cli1, fname, 0, 0);
8553         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8554
8555         if (!torture_close_connection(cli1)) {
8556                 correct = false;
8557         }
8558         if (!torture_close_connection(cli2)) {
8559                 correct = false;
8560         }
8561
8562         TALLOC_FREE(frame);
8563         return correct;
8564 }
8565
8566 /*
8567   Test setting EA's are rejected on symlinks.
8568  */
8569 static bool run_ea_symlink_test(int dummy)
8570 {
8571         static struct cli_state *cli;
8572         const char *fname = "posix_file_ea";
8573         const char *sname = "posix_symlink_ea";
8574         const char *ea_name = "testea_name";
8575         const char *ea_value = "testea_value";
8576         uint16_t fnum = (uint16_t)-1;
8577         bool correct = false;
8578         NTSTATUS status;
8579         size_t i, num_eas;
8580         struct ea_struct *eas = NULL;
8581         TALLOC_CTX *frame = NULL;
8582
8583         frame = talloc_stackframe();
8584
8585         printf("Starting EA symlink test\n");
8586
8587         if (!torture_open_connection(&cli, 0)) {
8588                 TALLOC_FREE(frame);
8589                 return false;
8590         }
8591
8592         smbXcli_conn_set_sockopt(cli->conn, sockops);
8593
8594         status = torture_setup_unix_extensions(cli);
8595         if (!NT_STATUS_IS_OK(status)) {
8596                 TALLOC_FREE(frame);
8597                 return false;
8598         }
8599
8600         cli_setatr(cli, fname, 0, 0);
8601         cli_posix_unlink(cli, fname);
8602         cli_setatr(cli, sname, 0, 0);
8603         cli_posix_unlink(cli, sname);
8604
8605         status = cli_ntcreate(cli,
8606                         fname,
8607                         0,
8608                         READ_CONTROL_ACCESS,
8609                         0,
8610                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8611                         FILE_CREATE,
8612                         0x0,
8613                         0x0,
8614                         &fnum,
8615                         NULL);
8616
8617         if (!NT_STATUS_IS_OK(status)) {
8618                 printf("cli_ntcreate of %s failed (%s)\n",
8619                         fname,
8620                         nt_errstr(status));
8621                 goto out;
8622         }
8623
8624         status = cli_close(cli, fnum);
8625         if (!NT_STATUS_IS_OK(status)) {
8626                 printf("close failed (%s)\n",
8627                         nt_errstr(status));
8628                 goto out;
8629         }
8630         fnum = (uint16_t)-1;
8631
8632         /* Set an EA on the path. */
8633         status = cli_set_ea_path(cli,
8634                                 fname,
8635                                 ea_name,
8636                                 ea_value,
8637                                 strlen(ea_value)+1);
8638
8639         if (!NT_STATUS_IS_OK(status)) {
8640                 printf("cli_set_ea_path failed (%s)\n",
8641                         nt_errstr(status));
8642                 goto out;
8643         }
8644
8645         /* Now create a symlink. */
8646         status = cli_posix_symlink(cli, fname, sname);
8647         if (!NT_STATUS_IS_OK(status)) {
8648                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8649                         sname,
8650                         fname,
8651                         nt_errstr(status));
8652                 goto out;
8653         }
8654
8655         /* Get the EA list on the path. Should return value set. */
8656         status = cli_get_ea_list_path(cli,
8657                                 fname,
8658                                 frame,
8659                                 &num_eas,
8660                                 &eas);
8661
8662         if (!NT_STATUS_IS_OK(status)) {
8663                 printf("cli_get_ea_list_path failed (%s)\n",
8664                         nt_errstr(status));
8665                 goto out;
8666         }
8667
8668         /* Ensure the EA we set is there. */
8669         for (i=0; i<num_eas; i++) {
8670                 if (strcmp(eas[i].name, ea_name) == 0 &&
8671                                 eas[i].value.length == strlen(ea_value)+1 &&
8672                                 memcmp(eas[i].value.data,
8673                                         ea_value,
8674                                         eas[i].value.length) == 0) {
8675                         break;
8676                 }
8677         }
8678
8679         if (i == num_eas) {
8680                 printf("Didn't find EA on pathname %s\n",
8681                         fname);
8682                 goto out;
8683         }
8684
8685         num_eas = 0;
8686         TALLOC_FREE(eas);
8687
8688         /* Get the EA list on the symlink. Should return empty list. */
8689         status = cli_get_ea_list_path(cli,
8690                                 sname,
8691                                 frame,
8692                                 &num_eas,
8693                                 &eas);
8694
8695         if (!NT_STATUS_IS_OK(status)) {
8696                 printf("cli_get_ea_list_path failed (%s)\n",
8697                         nt_errstr(status));
8698                 goto out;
8699         }
8700
8701         if (num_eas != 0) {
8702                 printf("cli_get_ea_list_path failed (%s)\n",
8703                         nt_errstr(status));
8704                 goto out;
8705         }
8706
8707         /* Set an EA on the symlink. Should fail. */
8708         status = cli_set_ea_path(cli,
8709                                 sname,
8710                                 ea_name,
8711                                 ea_value,
8712                                 strlen(ea_value)+1);
8713
8714         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8715                 printf("cli_set_ea_path on a symlink gave %s. "
8716                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8717                         nt_errstr(status));
8718                 goto out;
8719         }
8720
8721         printf("EA symlink test passed\n");
8722         correct = true;
8723
8724   out:
8725
8726         if (fnum != (uint16_t)-1) {
8727                 cli_close(cli, fnum);
8728                 fnum = (uint16_t)-1;
8729         }
8730
8731         cli_setatr(cli, sname, 0, 0);
8732         cli_posix_unlink(cli, sname);
8733         cli_setatr(cli, fname, 0, 0);
8734         cli_posix_unlink(cli, fname);
8735
8736         if (!torture_close_connection(cli)) {
8737                 correct = false;
8738         }
8739
8740         TALLOC_FREE(frame);
8741         return correct;
8742 }
8743
8744 /*
8745   Test POSIX locks are OFD-locks.
8746  */
8747 static bool run_posix_ofd_lock_test(int dummy)
8748 {
8749         static struct cli_state *cli;
8750         const char *fname = "posix_file";
8751         uint16_t fnum1 = (uint16_t)-1;
8752         uint16_t fnum2 = (uint16_t)-1;
8753         bool correct = false;
8754         NTSTATUS status;
8755         TALLOC_CTX *frame = NULL;
8756
8757         frame = talloc_stackframe();
8758
8759         printf("Starting POSIX ofd-lock test\n");
8760
8761         if (!torture_open_connection(&cli, 0)) {
8762                 TALLOC_FREE(frame);
8763                 return false;
8764         }
8765
8766         smbXcli_conn_set_sockopt(cli->conn, sockops);
8767
8768         status = torture_setup_unix_extensions(cli);
8769         if (!NT_STATUS_IS_OK(status)) {
8770                 TALLOC_FREE(frame);
8771                 return false;
8772         }
8773
8774         cli_setatr(cli, fname, 0, 0);
8775         cli_posix_unlink(cli, fname);
8776
8777         /* Open the file twice. */
8778         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8779                                 0600, &fnum1);
8780         if (!NT_STATUS_IS_OK(status)) {
8781                 printf("First POSIX open of %s failed\n", fname);
8782                 goto out;
8783         }
8784
8785         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8786         if (!NT_STATUS_IS_OK(status)) {
8787                 printf("First POSIX open of %s failed\n", fname);
8788                 goto out;
8789         }
8790
8791         /* Set a 0-50 lock on fnum1. */
8792         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8793         if (!NT_STATUS_IS_OK(status)) {
8794                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8795                 goto out;
8796         }
8797
8798         /* Set a 60-100 lock on fnum2. */
8799         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8800         if (!NT_STATUS_IS_OK(status)) {
8801                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8802                 goto out;
8803         }
8804
8805         /* close fnum1 - 0-50 lock should go away. */
8806         status = cli_close(cli, fnum1);
8807         if (!NT_STATUS_IS_OK(status)) {
8808                 printf("close failed (%s)\n",
8809                         nt_errstr(status));
8810                 goto out;
8811         }
8812         fnum1 = (uint16_t)-1;
8813
8814         /* Change the lock context. */
8815         cli_setpid(cli, cli_getpid(cli) + 1);
8816
8817         /* Re-open fnum1. */
8818         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8819         if (!NT_STATUS_IS_OK(status)) {
8820                 printf("Third POSIX open of %s failed\n", fname);
8821                 goto out;
8822         }
8823
8824         /* 60-100 lock should still be there. */
8825         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8826         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8827                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8828                 goto out;
8829         }
8830
8831         /* 0-50 lock should be gone. */
8832         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8833         if (!NT_STATUS_IS_OK(status)) {
8834                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8835                 goto out;
8836         }
8837
8838         printf("POSIX OFD lock test passed\n");
8839         correct = true;
8840
8841   out:
8842
8843         if (fnum1 != (uint16_t)-1) {
8844                 cli_close(cli, fnum1);
8845                 fnum1 = (uint16_t)-1;
8846         }
8847         if (fnum2 != (uint16_t)-1) {
8848                 cli_close(cli, fnum2);
8849                 fnum2 = (uint16_t)-1;
8850         }
8851
8852         cli_setatr(cli, fname, 0, 0);
8853         cli_posix_unlink(cli, fname);
8854
8855         if (!torture_close_connection(cli)) {
8856                 correct = false;
8857         }
8858
8859         TALLOC_FREE(frame);
8860         return correct;
8861 }
8862
8863 struct posix_blocking_state {
8864         struct tevent_context *ev;
8865         struct cli_state *cli1;
8866         uint16_t fnum1;
8867         struct cli_state *cli2;
8868         uint16_t fnum2;
8869         bool gotblocked;
8870         bool gotecho;
8871 };
8872
8873 static void posix_blocking_locked(struct tevent_req *subreq);
8874 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8875 static void posix_blocking_gotecho(struct tevent_req *subreq);
8876 static void posix_blocking_unlocked(struct tevent_req *subreq);
8877
8878 static struct tevent_req *posix_blocking_send(
8879         TALLOC_CTX *mem_ctx,
8880         struct tevent_context *ev,
8881         struct cli_state *cli1,
8882         uint16_t fnum1,
8883         struct cli_state *cli2,
8884         uint16_t fnum2)
8885 {
8886         struct tevent_req *req = NULL, *subreq = NULL;
8887         struct posix_blocking_state *state = NULL;
8888
8889         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8890         if (req == NULL) {
8891                 return NULL;
8892         }
8893         state->ev = ev;
8894         state->cli1 = cli1;
8895         state->fnum1 = fnum1;
8896         state->cli2 = cli2;
8897         state->fnum2 = fnum2;
8898
8899         subreq = cli_posix_lock_send(
8900                 state,
8901                 state->ev,
8902                 state->cli1,
8903                 state->fnum1,
8904                 0,
8905                 1,
8906                 false,
8907                 WRITE_LOCK);
8908         if (tevent_req_nomem(subreq, req)) {
8909                 return tevent_req_post(req, ev);
8910         }
8911         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8912         return req;
8913 }
8914
8915 static void posix_blocking_locked(struct tevent_req *subreq)
8916 {
8917         struct tevent_req *req = tevent_req_callback_data(
8918                 subreq, struct tevent_req);
8919         struct posix_blocking_state *state = tevent_req_data(
8920                 req, struct posix_blocking_state);
8921         NTSTATUS status;
8922
8923         status = cli_posix_lock_recv(subreq);
8924         TALLOC_FREE(subreq);
8925         if (tevent_req_nterror(req, status)) {
8926                 return;
8927         }
8928
8929         subreq = cli_posix_lock_send(
8930                 state,
8931                 state->ev,
8932                 state->cli2,
8933                 state->fnum2,
8934                 0,
8935                 1,
8936                 true,
8937                 WRITE_LOCK);
8938         if (tevent_req_nomem(subreq, req)) {
8939                 return;
8940         }
8941         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8942
8943         /* Make sure the blocking request is delivered */
8944         subreq = cli_echo_send(
8945                 state,
8946                 state->ev,
8947                 state->cli2,
8948                 1,
8949                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8950         if (tevent_req_nomem(subreq, req)) {
8951                 return;
8952         }
8953         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8954 }
8955
8956 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8957 {
8958         struct tevent_req *req = tevent_req_callback_data(
8959                 subreq, struct tevent_req);
8960         struct posix_blocking_state *state = tevent_req_data(
8961                 req, struct posix_blocking_state);
8962         NTSTATUS status;
8963
8964         status = cli_posix_lock_recv(subreq);
8965         TALLOC_FREE(subreq);
8966         if (tevent_req_nterror(req, status)) {
8967                 return;
8968         }
8969         if (!state->gotecho) {
8970                 printf("blocked req got through before echo\n");
8971                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8972                 return;
8973         }
8974         tevent_req_done(req);
8975 }
8976
8977 static void posix_blocking_gotecho(struct tevent_req *subreq)
8978 {
8979         struct tevent_req *req = tevent_req_callback_data(
8980                 subreq, struct tevent_req);
8981         struct posix_blocking_state *state = tevent_req_data(
8982                 req, struct posix_blocking_state);
8983         NTSTATUS status;
8984
8985         status = cli_echo_recv(subreq);
8986         TALLOC_FREE(subreq);
8987         if (tevent_req_nterror(req, status)) {
8988                 return;
8989         }
8990         if (state->gotblocked) {
8991                 printf("blocked req got through before echo\n");
8992                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8993                 return;
8994         }
8995         state->gotecho = true;
8996
8997         subreq = cli_posix_lock_send(
8998                 state,
8999                 state->ev,
9000                 state->cli1,
9001                 state->fnum1,
9002                 0,
9003                 1,
9004                 false,
9005                 UNLOCK_LOCK);
9006         if (tevent_req_nomem(subreq, req)) {
9007                 return;
9008         }
9009         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9010 }
9011
9012 static void posix_blocking_unlocked(struct tevent_req *subreq)
9013 {
9014         struct tevent_req *req = tevent_req_callback_data(
9015                 subreq, struct tevent_req);
9016         NTSTATUS status;
9017
9018         status = cli_posix_lock_recv(subreq);
9019         TALLOC_FREE(subreq);
9020         if (tevent_req_nterror(req, status)) {
9021                 return;
9022         }
9023         /* tevent_req_done in posix_blocking_gotlocked */
9024 }
9025
9026 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9027 {
9028         return tevent_req_simple_recv_ntstatus(req);
9029 }
9030
9031 static bool run_posix_blocking_lock(int dummy)
9032 {
9033         struct tevent_context *ev = NULL;
9034         struct cli_state *cli1 = NULL, *cli2 = NULL;
9035         const char *fname = "posix_blocking";
9036         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9037         struct tevent_req *req = NULL;
9038         NTSTATUS status;
9039         bool ret = false;
9040         bool ok;
9041
9042         printf("Starting posix blocking lock test\n");
9043
9044         ev = samba_tevent_context_init(NULL);
9045         if (ev == NULL) {
9046                 return false;
9047         }
9048
9049         ok = torture_open_connection(&cli1, 0);
9050         if (!ok) {
9051                 goto fail;
9052         }
9053         ok = torture_open_connection(&cli2, 0);
9054         if (!ok) {
9055                 goto fail;
9056         }
9057
9058         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9059
9060         status = torture_setup_unix_extensions(cli1);
9061         if (!NT_STATUS_IS_OK(status)) {
9062                 return false;
9063         }
9064
9065         status = torture_setup_unix_extensions(cli2);
9066         if (!NT_STATUS_IS_OK(status)) {
9067                 return false;
9068         }
9069
9070         cli_setatr(cli1, fname, 0, 0);
9071         cli_posix_unlink(cli1, fname);
9072
9073         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9074                                 0600, &fnum1);
9075         if (!NT_STATUS_IS_OK(status)) {
9076                 printf("First POSIX open of %s failed: %s\n",
9077                        fname,
9078                        nt_errstr(status));
9079                 goto fail;
9080         }
9081
9082         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9083         if (!NT_STATUS_IS_OK(status)) {
9084                 printf("Second POSIX open of %s failed: %s\n",
9085                        fname,
9086                        nt_errstr(status));
9087                 goto fail;
9088         }
9089
9090         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9091         if (req == NULL) {
9092                 printf("cli_posix_blocking failed\n");
9093                 goto fail;
9094         }
9095
9096         ok = tevent_req_poll_ntstatus(req, ev, &status);
9097         if (!ok) {
9098                 printf("tevent_req_poll_ntstatus failed: %s\n",
9099                        nt_errstr(status));
9100                 goto fail;
9101         }
9102         status = posix_blocking_recv(req);
9103         TALLOC_FREE(req);
9104         if (!NT_STATUS_IS_OK(status)) {
9105                 printf("posix_blocking_recv returned %s\n",
9106                        nt_errstr(status));
9107                 goto fail;
9108         }
9109
9110         ret = true;
9111 fail:
9112
9113         if (fnum1 != UINT16_MAX) {
9114                 cli_close(cli1, fnum1);
9115                 fnum1 = UINT16_MAX;
9116         }
9117         if (fnum2 != UINT16_MAX) {
9118                 cli_close(cli2, fnum2);
9119                 fnum2 = UINT16_MAX;
9120         }
9121
9122         if (cli1 != NULL) {
9123                 cli_setatr(cli1, fname, 0, 0);
9124                 cli_posix_unlink(cli1, fname);
9125         }
9126
9127         ok = true;
9128
9129         if (cli1 != NULL) {
9130                 ok &= torture_close_connection(cli1);
9131                 cli1 = NULL;
9132         }
9133         if (cli2 != NULL) {
9134                 ok &= torture_close_connection(cli2);
9135                 cli2 = NULL;
9136         }
9137
9138         if (!ok) {
9139                 ret = false;
9140         }
9141         TALLOC_FREE(ev);
9142         return ret;
9143 }
9144
9145 /*
9146   Test POSIX mkdir is case-sensitive.
9147  */
9148 static bool run_posix_mkdir_test(int dummy)
9149 {
9150         static struct cli_state *cli;
9151         const char *fname_foo = "POSIX_foo";
9152         const char *fname_foo_Foo = "POSIX_foo/Foo";
9153         const char *fname_foo_foo = "POSIX_foo/foo";
9154         const char *fname_Foo = "POSIX_Foo";
9155         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9156         const char *fname_Foo_foo = "POSIX_Foo/foo";
9157         bool correct = false;
9158         NTSTATUS status;
9159         TALLOC_CTX *frame = NULL;
9160         uint16_t fnum = (uint16_t)-1;
9161
9162         frame = talloc_stackframe();
9163
9164         printf("Starting POSIX mkdir test\n");
9165
9166         if (!torture_open_connection(&cli, 0)) {
9167                 TALLOC_FREE(frame);
9168                 return false;
9169         }
9170
9171         smbXcli_conn_set_sockopt(cli->conn, sockops);
9172
9173         status = torture_setup_unix_extensions(cli);
9174         if (!NT_STATUS_IS_OK(status)) {
9175                 TALLOC_FREE(frame);
9176                 return false;
9177         }
9178
9179         cli_posix_rmdir(cli, fname_foo_foo);
9180         cli_posix_rmdir(cli, fname_foo_Foo);
9181         cli_posix_rmdir(cli, fname_foo);
9182
9183         cli_posix_rmdir(cli, fname_Foo_foo);
9184         cli_posix_rmdir(cli, fname_Foo_Foo);
9185         cli_posix_rmdir(cli, fname_Foo);
9186
9187         /*
9188          * Create a file POSIX_foo then try
9189          * and use it in a directory path by
9190          * doing mkdir POSIX_foo/bar.
9191          * The mkdir should fail with
9192          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9193          */
9194
9195         status = cli_posix_open(cli,
9196                         fname_foo,
9197                         O_RDWR|O_CREAT,
9198                         0666,
9199                         &fnum);
9200         if (!NT_STATUS_IS_OK(status)) {
9201                 printf("cli_posix_open of %s failed error %s\n",
9202                         fname_foo,
9203                         nt_errstr(status));
9204                 goto out;
9205         }
9206
9207         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9208         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9209                 printf("cli_posix_mkdir of %s should fail with "
9210                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9211                         "%s instead\n",
9212                         fname_foo_foo,
9213                         nt_errstr(status));
9214                 goto out;
9215         }
9216
9217         status = cli_close(cli, fnum);
9218         if (!NT_STATUS_IS_OK(status)) {
9219                 printf("cli_close failed %s\n", nt_errstr(status));
9220                 goto out;
9221         }
9222         fnum = (uint16_t)-1;
9223
9224         status = cli_posix_unlink(cli, fname_foo);
9225         if (!NT_STATUS_IS_OK(status)) {
9226                 printf("cli_posix_unlink of %s failed error %s\n",
9227                         fname_foo,
9228                         nt_errstr(status));
9229                 goto out;
9230         }
9231
9232         /*
9233          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9234          * posix_open, posix_unlink, on
9235          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9236          * not silently create POSIX_foo/foo.
9237          */
9238
9239         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9240         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9241                 printf("cli_posix_mkdir of %s should fail with "
9242                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9243                         "%s instead\n",
9244                         fname_foo_foo,
9245                         nt_errstr(status));
9246                 goto out;
9247         }
9248
9249         status = cli_posix_rmdir(cli, fname_foo_foo);
9250         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9251                 printf("cli_posix_rmdir of %s should fail with "
9252                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9253                         "%s instead\n",
9254                         fname_foo_foo,
9255                         nt_errstr(status));
9256                 goto out;
9257         }
9258
9259         status = cli_posix_open(cli,
9260                         fname_foo_foo,
9261                         O_RDWR|O_CREAT,
9262                         0666,
9263                         &fnum);
9264         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9265                 printf("cli_posix_open of %s should fail with "
9266                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9267                         "%s instead\n",
9268                         fname_foo_foo,
9269                         nt_errstr(status));
9270                 goto out;
9271         }
9272
9273         status = cli_posix_unlink(cli, fname_foo_foo);
9274         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9275                 printf("cli_posix_unlink of %s should fail with "
9276                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9277                         "%s instead\n",
9278                         fname_foo_foo,
9279                         nt_errstr(status));
9280                 goto out;
9281         }
9282
9283         status = cli_posix_mkdir(cli, fname_foo, 0777);
9284         if (!NT_STATUS_IS_OK(status)) {
9285                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9286                 goto out;
9287         }
9288
9289         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9290         if (!NT_STATUS_IS_OK(status)) {
9291                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9292                 goto out;
9293         }
9294
9295         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9296         if (!NT_STATUS_IS_OK(status)) {
9297                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9298                 goto out;
9299         }
9300
9301         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9302         if (!NT_STATUS_IS_OK(status)) {
9303                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9304                 goto out;
9305         }
9306
9307         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9308         if (!NT_STATUS_IS_OK(status)) {
9309                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9310                 goto out;
9311         }
9312
9313         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9314         if (!NT_STATUS_IS_OK(status)) {
9315                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9316                 goto out;
9317         }
9318
9319         printf("POSIX mkdir test passed\n");
9320         correct = true;
9321
9322   out:
9323
9324         if (fnum != (uint16_t)-1) {
9325                 cli_close(cli, fnum);
9326                 fnum = (uint16_t)-1;
9327         }
9328
9329         cli_posix_rmdir(cli, fname_foo_foo);
9330         cli_posix_rmdir(cli, fname_foo_Foo);
9331         cli_posix_rmdir(cli, fname_foo);
9332
9333         cli_posix_rmdir(cli, fname_Foo_foo);
9334         cli_posix_rmdir(cli, fname_Foo_Foo);
9335         cli_posix_rmdir(cli, fname_Foo);
9336
9337         if (!torture_close_connection(cli)) {
9338                 correct = false;
9339         }
9340
9341         TALLOC_FREE(frame);
9342         return correct;
9343 }
9344
9345 struct posix_acl_oplock_state {
9346         struct tevent_context *ev;
9347         struct cli_state *cli;
9348         bool *got_break;
9349         bool *acl_ret;
9350         NTSTATUS status;
9351 };
9352
9353 static void posix_acl_oplock_got_break(struct tevent_req *req)
9354 {
9355         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9356                 req, struct posix_acl_oplock_state);
9357         uint16_t fnum;
9358         uint8_t level;
9359         NTSTATUS status;
9360
9361         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9362         TALLOC_FREE(req);
9363         if (!NT_STATUS_IS_OK(status)) {
9364                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9365                        nt_errstr(status));
9366                 return;
9367         }
9368         *state->got_break = true;
9369
9370         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9371                                   NO_OPLOCK);
9372         if (req == NULL) {
9373                 printf("cli_oplock_ack_send failed\n");
9374                 return;
9375         }
9376 }
9377
9378 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9379 {
9380         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9381                 req, struct posix_acl_oplock_state);
9382         size_t ret_size = 0;
9383         char *ret_data = NULL;
9384
9385         state->status = cli_posix_getacl_recv(req,
9386                         state,
9387                         &ret_size,
9388                         &ret_data);
9389
9390         if (!NT_STATUS_IS_OK(state->status)) {
9391                 printf("cli_posix_getacl_recv returned %s\n",
9392                         nt_errstr(state->status));
9393         }
9394         *state->acl_ret = true;
9395 }
9396
9397 static bool run_posix_acl_oplock_test(int dummy)
9398 {
9399         struct tevent_context *ev;
9400         struct cli_state *cli1, *cli2;
9401         struct tevent_req *oplock_req, *getacl_req;
9402         const char *fname = "posix_acl_oplock";
9403         uint16_t fnum;
9404         int saved_use_oplocks = use_oplocks;
9405         NTSTATUS status;
9406         bool correct = true;
9407         bool got_break = false;
9408         bool acl_ret = false;
9409
9410         struct posix_acl_oplock_state *state;
9411
9412         printf("starting posix_acl_oplock test\n");
9413
9414         if (!torture_open_connection(&cli1, 0)) {
9415                 use_level_II_oplocks = false;
9416                 use_oplocks = saved_use_oplocks;
9417                 return false;
9418         }
9419
9420         if (!torture_open_connection(&cli2, 1)) {
9421                 use_level_II_oplocks = false;
9422                 use_oplocks = saved_use_oplocks;
9423                 return false;
9424         }
9425
9426         /* Setup posix on cli2 only. */
9427         status = torture_setup_unix_extensions(cli2);
9428         if (!NT_STATUS_IS_OK(status)) {
9429                 return false;
9430         }
9431
9432         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9433         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9434
9435         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9436
9437         /* Create the file on the Windows connection. */
9438         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9439                           &fnum);
9440         if (!NT_STATUS_IS_OK(status)) {
9441                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9442                 return false;
9443         }
9444
9445         status = cli_close(cli1, fnum);
9446         if (!NT_STATUS_IS_OK(status)) {
9447                 printf("close1 failed (%s)\n", nt_errstr(status));
9448                 return false;
9449         }
9450
9451         cli1->use_oplocks = true;
9452
9453         /* Open with oplock. */
9454         status = cli_ntcreate(cli1,
9455                         fname,
9456                         0,
9457                         FILE_READ_DATA,
9458                         FILE_ATTRIBUTE_NORMAL,
9459                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9460                         FILE_OPEN,
9461                         0,
9462                         0,
9463                         &fnum,
9464                         NULL);
9465
9466         if (!NT_STATUS_IS_OK(status)) {
9467                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9468                 return false;
9469         }
9470
9471         ev = samba_tevent_context_init(talloc_tos());
9472         if (ev == NULL) {
9473                 printf("tevent_context_init failed\n");
9474                 return false;
9475         }
9476
9477         state = talloc_zero(ev, struct posix_acl_oplock_state);
9478         if (state == NULL) {
9479                 printf("talloc failed\n");
9480                 return false;
9481         }
9482         state->ev = ev;
9483         state->cli = cli1;
9484         state->got_break = &got_break;
9485         state->acl_ret = &acl_ret;
9486
9487         oplock_req = cli_smb_oplock_break_waiter_send(
9488                 talloc_tos(), ev, cli1);
9489         if (oplock_req == NULL) {
9490                 printf("cli_smb_oplock_break_waiter_send failed\n");
9491                 return false;
9492         }
9493         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9494
9495         /* Get ACL on POSIX connection - should break oplock. */
9496         getacl_req = cli_posix_getacl_send(talloc_tos(),
9497                                 ev,
9498                                 cli2,
9499                                 fname);
9500         if (getacl_req == NULL) {
9501                 printf("cli_posix_getacl_send failed\n");
9502                 return false;
9503         }
9504         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9505
9506         while (!got_break || !acl_ret) {
9507                 int ret;
9508                 ret = tevent_loop_once(ev);
9509                 if (ret == -1) {
9510                         printf("tevent_loop_once failed: %s\n",
9511                                strerror(errno));
9512                         return false;
9513                 }
9514         }
9515
9516         if (!NT_STATUS_IS_OK(state->status)) {
9517                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9518                 correct = false;
9519         }
9520
9521         status = cli_close(cli1, fnum);
9522         if (!NT_STATUS_IS_OK(status)) {
9523                 printf("close2 failed (%s)\n", nt_errstr(status));
9524                 correct = false;
9525         }
9526
9527         status = cli_unlink(cli1,
9528                         fname,
9529                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9530         if (!NT_STATUS_IS_OK(status)) {
9531                 printf("unlink failed (%s)\n", nt_errstr(status));
9532                 correct = false;
9533         }
9534
9535         if (!torture_close_connection(cli1)) {
9536                 correct = false;
9537         }
9538         if (!torture_close_connection(cli2)) {
9539                 correct = false;
9540         }
9541
9542         if (!got_break) {
9543                 correct = false;
9544         }
9545
9546         printf("finished posix acl oplock test\n");
9547
9548         return correct;
9549 }
9550
9551 static bool run_posix_acl_shareroot_test(int dummy)
9552 {
9553         struct cli_state *cli;
9554         NTSTATUS status;
9555         bool correct = false;
9556         char *posix_acl = NULL;
9557         size_t posix_acl_len = 0;
9558         uint16_t num_file_acls = 0;
9559         uint16_t num_dir_acls = 0;
9560         uint16_t i;
9561         uint32_t expected_size = 0;
9562         bool got_user = false;
9563         bool got_group = false;
9564         bool got_other = false;
9565         TALLOC_CTX *frame = NULL;
9566
9567         frame = talloc_stackframe();
9568
9569         printf("starting posix_acl_shareroot test\n");
9570
9571         if (!torture_open_connection(&cli, 0)) {
9572                 TALLOC_FREE(frame);
9573                 return false;
9574         }
9575
9576         smbXcli_conn_set_sockopt(cli->conn, sockops);
9577
9578         status = torture_setup_unix_extensions(cli);
9579         if (!NT_STATUS_IS_OK(status)) {
9580                 printf("Failed to setup unix extensions\n");
9581                 goto out;
9582         }
9583
9584         /* Get the POSIX ACL on the root of the share. */
9585         status = cli_posix_getacl(cli,
9586                                 ".",
9587                                 frame,
9588                                 &posix_acl_len,
9589                                 &posix_acl);
9590
9591         if (!NT_STATUS_IS_OK(status)) {
9592                 printf("cli_posix_getacl of '.' failed (%s)\n",
9593                         nt_errstr(status));
9594                 goto out;
9595         }
9596
9597         if (posix_acl_len < 6 ||
9598                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9599                 printf("getfacl ., unknown POSIX acl version %u.\n",
9600                         (unsigned int)CVAL(posix_acl,0) );
9601                 goto out;
9602         }
9603
9604         num_file_acls = SVAL(posix_acl,2);
9605         num_dir_acls = SVAL(posix_acl,4);
9606         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9607                                 SMB_POSIX_ACL_ENTRY_SIZE*
9608                                 (num_file_acls+num_dir_acls);
9609
9610         if (posix_acl_len != expected_size) {
9611                 printf("incorrect POSIX acl buffer size "
9612                         "(should be %u, was %u).\n",
9613                         (unsigned int)expected_size,
9614                         (unsigned int)posix_acl_len);
9615                 goto out;
9616         }
9617
9618         /*
9619          * We don't need to know what the ACL's are
9620          * we just need to know we have at least 3
9621          * file entries (u,g,o).
9622          */
9623
9624         for (i = 0; i < num_file_acls; i++) {
9625                 unsigned char tagtype =
9626                         CVAL(posix_acl,
9627                                 SMB_POSIX_ACL_HEADER_SIZE+
9628                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9629
9630                 switch(tagtype) {
9631                         case SMB_POSIX_ACL_USER_OBJ:
9632                                 got_user = true;
9633                                 break;
9634                         case SMB_POSIX_ACL_GROUP_OBJ:
9635                                 got_group = true;
9636                                 break;
9637                         case SMB_POSIX_ACL_OTHER:
9638                                 got_other = true;
9639                                 break;
9640                         default:
9641                                 break;
9642                 }
9643         }
9644
9645         if (!got_user) {
9646                 printf("Missing user entry\n");
9647                 goto out;
9648         }
9649
9650         if (!got_group) {
9651                 printf("Missing group entry\n");
9652                 goto out;
9653         }
9654
9655         if (!got_other) {
9656                 printf("Missing other entry\n");
9657                 goto out;
9658         }
9659
9660         correct = true;
9661
9662   out:
9663
9664         if (!torture_close_connection(cli)) {
9665                 correct = false;
9666         }
9667
9668         printf("finished posix acl shareroot test\n");
9669         TALLOC_FREE(frame);
9670
9671         return correct;
9672 }
9673
9674 static uint32_t open_attrs_table[] = {
9675                 FILE_ATTRIBUTE_NORMAL,
9676                 FILE_ATTRIBUTE_ARCHIVE,
9677                 FILE_ATTRIBUTE_READONLY,
9678                 FILE_ATTRIBUTE_HIDDEN,
9679                 FILE_ATTRIBUTE_SYSTEM,
9680
9681                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9682                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9683                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9684                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9685                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9686                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9687
9688                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9689                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9690                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9691                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9692 };
9693
9694 struct trunc_open_results {
9695         unsigned int num;
9696         uint32_t init_attr;
9697         uint32_t trunc_attr;
9698         uint32_t result_attr;
9699 };
9700
9701 static struct trunc_open_results attr_results[] = {
9702         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9703         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9704         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9705         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9706         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9707         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9708         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9709         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9710         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9711         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9712         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9713         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9714         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9715         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716         { 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 },
9717         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9718         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719         { 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 },
9720         { 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 },
9721         { 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 },
9722         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9723         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9724         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9725         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9726         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9727         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9728 };
9729
9730 static bool run_openattrtest(int dummy)
9731 {
9732         static struct cli_state *cli1;
9733         const char *fname = "\\openattr.file";
9734         uint16_t fnum1;
9735         bool correct = True;
9736         uint32_t attr;
9737         unsigned int i, j, k, l;
9738         NTSTATUS status;
9739
9740         printf("starting open attr test\n");
9741
9742         if (!torture_open_connection(&cli1, 0)) {
9743                 return False;
9744         }
9745
9746         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9747
9748         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9749                 cli_setatr(cli1, fname, 0, 0);
9750                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9751
9752                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9753                                        open_attrs_table[i], FILE_SHARE_NONE,
9754                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9755                 if (!NT_STATUS_IS_OK(status)) {
9756                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9757                         return False;
9758                 }
9759
9760                 status = cli_close(cli1, fnum1);
9761                 if (!NT_STATUS_IS_OK(status)) {
9762                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9763                         return False;
9764                 }
9765
9766                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9767                         status = cli_ntcreate(cli1, fname, 0,
9768                                               FILE_READ_DATA|FILE_WRITE_DATA,
9769                                               open_attrs_table[j],
9770                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9771                                               0, 0, &fnum1, NULL);
9772                         if (!NT_STATUS_IS_OK(status)) {
9773                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9774                                         if (attr_results[l].num == k) {
9775                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9776                                                                 k, open_attrs_table[i],
9777                                                                 open_attrs_table[j],
9778                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9779                                                 correct = False;
9780                                         }
9781                                 }
9782
9783                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9784                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9785                                                         k, open_attrs_table[i], open_attrs_table[j],
9786                                                         nt_errstr(status));
9787                                         correct = False;
9788                                 }
9789 #if 0
9790                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9791 #endif
9792                                 k++;
9793                                 continue;
9794                         }
9795
9796                         status = cli_close(cli1, fnum1);
9797                         if (!NT_STATUS_IS_OK(status)) {
9798                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9799                                 return False;
9800                         }
9801
9802                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9803                         if (!NT_STATUS_IS_OK(status)) {
9804                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9805                                 return False;
9806                         }
9807
9808 #if 0
9809                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9810                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9811 #endif
9812
9813                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9814                                 if (attr_results[l].num == k) {
9815                                         if (attr != attr_results[l].result_attr ||
9816                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9817                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9818                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9819                                                 open_attrs_table[i],
9820                                                 open_attrs_table[j],
9821                                                 (unsigned int)attr,
9822                                                 attr_results[l].result_attr);
9823                                                 correct = False;
9824                                         }
9825                                         break;
9826                                 }
9827                         }
9828                         k++;
9829                 }
9830         }
9831
9832         cli_setatr(cli1, fname, 0, 0);
9833         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9834
9835         printf("open attr test %s.\n", correct ? "passed" : "failed");
9836
9837         if (!torture_close_connection(cli1)) {
9838                 correct = False;
9839         }
9840         return correct;
9841 }
9842
9843 static NTSTATUS list_fn(struct file_info *finfo,
9844                     const char *name, void *state)
9845 {
9846         int *matched = (int *)state;
9847         if (matched != NULL) {
9848                 *matched += 1;
9849         }
9850         return NT_STATUS_OK;
9851 }
9852
9853 /*
9854   test directory listing speed
9855  */
9856 static bool run_dirtest(int dummy)
9857 {
9858         int i;
9859         static struct cli_state *cli;
9860         uint16_t fnum;
9861         struct timeval core_start;
9862         bool correct = True;
9863         int matched;
9864
9865         printf("starting directory test\n");
9866
9867         if (!torture_open_connection(&cli, 0)) {
9868                 return False;
9869         }
9870
9871         smbXcli_conn_set_sockopt(cli->conn, sockops);
9872
9873         srandom(0);
9874         for (i=0;i<torture_numops;i++) {
9875                 fstring fname;
9876                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9877                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9878                         fprintf(stderr,"Failed to open %s\n", fname);
9879                         return False;
9880                 }
9881                 cli_close(cli, fnum);
9882         }
9883
9884         core_start = timeval_current();
9885
9886         matched = 0;
9887         cli_list(cli, "a*.*", 0, list_fn, &matched);
9888         printf("Matched %d\n", matched);
9889
9890         matched = 0;
9891         cli_list(cli, "b*.*", 0, list_fn, &matched);
9892         printf("Matched %d\n", matched);
9893
9894         matched = 0;
9895         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9896         printf("Matched %d\n", matched);
9897
9898         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9899
9900         srandom(0);
9901         for (i=0;i<torture_numops;i++) {
9902                 fstring fname;
9903                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9904                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9905         }
9906
9907         if (!torture_close_connection(cli)) {
9908                 correct = False;
9909         }
9910
9911         printf("finished dirtest\n");
9912
9913         return correct;
9914 }
9915
9916 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9917                    void *state)
9918 {
9919         struct cli_state *pcli = (struct cli_state *)state;
9920         fstring fname;
9921         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9922
9923         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9924                 return NT_STATUS_OK;
9925
9926         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9927                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9928                         printf("del_fn: failed to rmdir %s\n,", fname );
9929         } else {
9930                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9931                         printf("del_fn: failed to unlink %s\n,", fname );
9932         }
9933         return NT_STATUS_OK;
9934 }
9935
9936
9937 /*
9938    send a raw ioctl - used by the torture code
9939 */
9940 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9941                               uint16_t fnum,
9942                               uint32_t code,
9943                               DATA_BLOB *blob)
9944 {
9945         uint16_t vwv[3];
9946         NTSTATUS status;
9947
9948         PUSH_LE_U16(vwv + 0, 0, fnum);
9949         PUSH_LE_U16(vwv + 1, 0, code >> 16);
9950         PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9951
9952         status = cli_smb(talloc_tos(),
9953                          cli,
9954                          SMBioctl,
9955                          0,
9956                          3,
9957                          vwv,
9958                          0,
9959                          NULL,
9960                          NULL,
9961                          0,
9962                          NULL,
9963                          NULL,
9964                          NULL,
9965                          NULL);
9966         if (!NT_STATUS_IS_OK(status)) {
9967                 return status;
9968         }
9969         *blob = data_blob_null;
9970         return NT_STATUS_OK;
9971 }
9972
9973 /*
9974   sees what IOCTLs are supported
9975  */
9976 bool torture_ioctl_test(int dummy)
9977 {
9978         static struct cli_state *cli;
9979         uint16_t device, function;
9980         uint16_t fnum;
9981         const char *fname = "\\ioctl.dat";
9982         DATA_BLOB blob;
9983         NTSTATUS status;
9984
9985         if (!torture_open_connection(&cli, 0)) {
9986                 return False;
9987         }
9988
9989         printf("starting ioctl test\n");
9990
9991         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9992
9993         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9994         if (!NT_STATUS_IS_OK(status)) {
9995                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9996                 return False;
9997         }
9998
9999         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
10000         printf("ioctl device info: %s\n", nt_errstr(status));
10001
10002         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
10003         printf("ioctl job info: %s\n", nt_errstr(status));
10004
10005         for (device=0;device<0x100;device++) {
10006                 printf("ioctl test with device = 0x%x\n", device);
10007                 for (function=0;function<0x100;function++) {
10008                         uint32_t code = (device<<16) | function;
10009
10010                         status = cli_raw_ioctl(cli, fnum, code, &blob);
10011
10012                         if (NT_STATUS_IS_OK(status)) {
10013                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10014                                        (int)blob.length);
10015                                 data_blob_free(&blob);
10016                         }
10017                 }
10018         }
10019
10020         if (!torture_close_connection(cli)) {
10021                 return False;
10022         }
10023
10024         return True;
10025 }
10026
10027
10028 /*
10029   tries variants of chkpath
10030  */
10031 bool torture_chkpath_test(int dummy)
10032 {
10033         static struct cli_state *cli;
10034         uint16_t fnum;
10035         bool ret;
10036         NTSTATUS status;
10037
10038         if (!torture_open_connection(&cli, 0)) {
10039                 return False;
10040         }
10041
10042         printf("starting chkpath test\n");
10043
10044         /* cleanup from an old run */
10045         torture_deltree(cli, "\\chkpath.dir");
10046
10047         status = cli_mkdir(cli, "\\chkpath.dir");
10048         if (!NT_STATUS_IS_OK(status)) {
10049                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10050                 return False;
10051         }
10052
10053         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10054         if (!NT_STATUS_IS_OK(status)) {
10055                 printf("mkdir2 failed : %s\n", nt_errstr(status));
10056                 return False;
10057         }
10058
10059         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10060                           DENY_NONE, &fnum);
10061         if (!NT_STATUS_IS_OK(status)) {
10062                 printf("open1 failed (%s)\n", nt_errstr(status));
10063                 return False;
10064         }
10065         cli_close(cli, fnum);
10066
10067         status = cli_chkpath(cli, "\\chkpath.dir");
10068         if (!NT_STATUS_IS_OK(status)) {
10069                 printf("chkpath1 failed: %s\n", nt_errstr(status));
10070                 ret = False;
10071         }
10072
10073         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10074         if (!NT_STATUS_IS_OK(status)) {
10075                 printf("chkpath2 failed: %s\n", nt_errstr(status));
10076                 ret = False;
10077         }
10078
10079         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10080         if (!NT_STATUS_IS_OK(status)) {
10081                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10082                                   NT_STATUS_NOT_A_DIRECTORY);
10083         } else {
10084                 printf("* chkpath on a file should fail\n");
10085                 ret = False;
10086         }
10087
10088         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10089         if (!NT_STATUS_IS_OK(status)) {
10090                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10091                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
10092         } else {
10093                 printf("* chkpath on a non existent file should fail\n");
10094                 ret = False;
10095         }
10096
10097         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10098         if (!NT_STATUS_IS_OK(status)) {
10099                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10100                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
10101         } else {
10102                 printf("* chkpath on a non existent component should fail\n");
10103                 ret = False;
10104         }
10105
10106         torture_deltree(cli, "\\chkpath.dir");
10107
10108         if (!torture_close_connection(cli)) {
10109                 return False;
10110         }
10111
10112         return ret;
10113 }
10114
10115 static bool run_eatest(int dummy)
10116 {
10117         static struct cli_state *cli;
10118         const char *fname = "\\eatest.txt";
10119         bool correct = True;
10120         uint16_t fnum;
10121         size_t i, num_eas;
10122         struct ea_struct *ea_list = NULL;
10123         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10124         NTSTATUS status;
10125
10126         printf("starting eatest\n");
10127
10128         if (!torture_open_connection(&cli, 0)) {
10129                 talloc_destroy(mem_ctx);
10130                 return False;
10131         }
10132
10133         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10134
10135         status = cli_ntcreate(cli, fname, 0,
10136                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10137                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10138                               0x4044, 0, &fnum, NULL);
10139         if (!NT_STATUS_IS_OK(status)) {
10140                 printf("open failed - %s\n", nt_errstr(status));
10141                 talloc_destroy(mem_ctx);
10142                 return False;
10143         }
10144
10145         for (i = 0; i < 10; i++) {
10146                 fstring ea_name, ea_val;
10147
10148                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10149                 memset(ea_val, (char)i+1, i+1);
10150                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10151                 if (!NT_STATUS_IS_OK(status)) {
10152                         printf("ea_set of name %s failed - %s\n", ea_name,
10153                                nt_errstr(status));
10154                         talloc_destroy(mem_ctx);
10155                         return False;
10156                 }
10157         }
10158
10159         cli_close(cli, fnum);
10160         for (i = 0; i < 10; i++) {
10161                 fstring ea_name, ea_val;
10162
10163                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10164                 memset(ea_val, (char)i+1, i+1);
10165                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10166                 if (!NT_STATUS_IS_OK(status)) {
10167                         printf("ea_set of name %s failed - %s\n", ea_name,
10168                                nt_errstr(status));
10169                         talloc_destroy(mem_ctx);
10170                         return False;
10171                 }
10172         }
10173
10174         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10175         if (!NT_STATUS_IS_OK(status)) {
10176                 printf("ea_get list failed - %s\n", nt_errstr(status));
10177                 correct = False;
10178         }
10179
10180         printf("num_eas = %d\n", (int)num_eas);
10181
10182         if (num_eas != 20) {
10183                 printf("Should be 20 EA's stored... failing.\n");
10184                 correct = False;
10185         }
10186
10187         for (i = 0; i < num_eas; i++) {
10188                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10189                 dump_data(0, ea_list[i].value.data,
10190                           ea_list[i].value.length);
10191         }
10192
10193         /* Setting EA's to zero length deletes them. Test this */
10194         printf("Now deleting all EA's - case independent....\n");
10195
10196 #if 1
10197         cli_set_ea_path(cli, fname, "", "", 0);
10198 #else
10199         for (i = 0; i < 20; i++) {
10200                 fstring ea_name;
10201                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10202                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10203                 if (!NT_STATUS_IS_OK(status)) {
10204                         printf("ea_set of name %s failed - %s\n", ea_name,
10205                                nt_errstr(status));
10206                         talloc_destroy(mem_ctx);
10207                         return False;
10208                 }
10209         }
10210 #endif
10211
10212         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10213         if (!NT_STATUS_IS_OK(status)) {
10214                 printf("ea_get list failed - %s\n", nt_errstr(status));
10215                 correct = False;
10216         }
10217
10218         printf("num_eas = %d\n", (int)num_eas);
10219         for (i = 0; i < num_eas; i++) {
10220                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10221                 dump_data(0, ea_list[i].value.data,
10222                           ea_list[i].value.length);
10223         }
10224
10225         if (num_eas != 0) {
10226                 printf("deleting EA's failed.\n");
10227                 correct = False;
10228         }
10229
10230         /* Try and delete a non existent EA. */
10231         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10232         if (!NT_STATUS_IS_OK(status)) {
10233                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10234                        nt_errstr(status));
10235                 correct = False;
10236         }
10237
10238         talloc_destroy(mem_ctx);
10239         if (!torture_close_connection(cli)) {
10240                 correct = False;
10241         }
10242
10243         return correct;
10244 }
10245
10246 static bool run_dirtest1(int dummy)
10247 {
10248         int i;
10249         static struct cli_state *cli;
10250         uint16_t fnum;
10251         int num_seen;
10252         bool correct = True;
10253
10254         printf("starting directory test\n");
10255
10256         if (!torture_open_connection(&cli, 0)) {
10257                 return False;
10258         }
10259
10260         smbXcli_conn_set_sockopt(cli->conn, sockops);
10261
10262         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10263         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10264         cli_rmdir(cli, "\\LISTDIR");
10265         cli_mkdir(cli, "\\LISTDIR");
10266
10267         /* Create 1000 files and 1000 directories. */
10268         for (i=0;i<1000;i++) {
10269                 fstring fname;
10270                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10271                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10272                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10273                                    0, 0, &fnum, NULL))) {
10274                         fprintf(stderr,"Failed to open %s\n", fname);
10275                         return False;
10276                 }
10277                 cli_close(cli, fnum);
10278         }
10279         for (i=0;i<1000;i++) {
10280                 fstring fname;
10281                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10282                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10283                         fprintf(stderr,"Failed to open %s\n", fname);
10284                         return False;
10285                 }
10286         }
10287
10288         /* Now ensure that doing an old list sees both files and directories. */
10289         num_seen = 0;
10290         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10291         printf("num_seen = %d\n", num_seen );
10292         /* We should see 100 files + 1000 directories + . and .. */
10293         if (num_seen != 2002)
10294                 correct = False;
10295
10296         /* Ensure if we have the "must have" bits we only see the
10297          * relevant entries.
10298          */
10299         num_seen = 0;
10300         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10301         printf("num_seen = %d\n", num_seen );
10302         if (num_seen != 1002)
10303                 correct = False;
10304
10305         num_seen = 0;
10306         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10307         printf("num_seen = %d\n", num_seen );
10308         if (num_seen != 1000)
10309                 correct = False;
10310
10311         /* Delete everything. */
10312         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10313         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10314         cli_rmdir(cli, "\\LISTDIR");
10315
10316 #if 0
10317         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10318         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10319         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10320 #endif
10321
10322         if (!torture_close_connection(cli)) {
10323                 correct = False;
10324         }
10325
10326         printf("finished dirtest1\n");
10327
10328         return correct;
10329 }
10330
10331 static bool run_error_map_extract(int dummy) {
10332
10333         static struct cli_state *c_dos;
10334         static struct cli_state *c_nt;
10335         NTSTATUS status;
10336
10337         uint32_t error;
10338
10339         uint32_t errnum;
10340         uint8_t errclass;
10341
10342         NTSTATUS nt_status;
10343
10344         fstring user;
10345
10346         /* NT-Error connection */
10347
10348         disable_spnego = true;
10349         if (!(c_nt = open_nbt_connection())) {
10350                 disable_spnego = false;
10351                 return False;
10352         }
10353         disable_spnego = false;
10354
10355         status = smbXcli_negprot(c_nt->conn,
10356                                  c_nt->timeout,
10357                                  PROTOCOL_CORE,
10358                                  PROTOCOL_NT1,
10359                                  NULL,
10360                                  NULL,
10361                                  NULL);
10362
10363         if (!NT_STATUS_IS_OK(status)) {
10364                 printf("%s rejected the NT-error negprot (%s)\n", host,
10365                        nt_errstr(status));
10366                 cli_shutdown(c_nt);
10367                 return False;
10368         }
10369
10370         status = cli_session_setup_anon(c_nt);
10371         if (!NT_STATUS_IS_OK(status)) {
10372                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10373                 return False;
10374         }
10375
10376         /* DOS-Error connection */
10377
10378         disable_spnego = true;
10379         force_dos_errors = true;
10380         if (!(c_dos = open_nbt_connection())) {
10381                 disable_spnego = false;
10382                 force_dos_errors = false;
10383                 return False;
10384         }
10385         disable_spnego = false;
10386         force_dos_errors = false;
10387
10388         status = smbXcli_negprot(c_dos->conn,
10389                                  c_dos->timeout,
10390                                  PROTOCOL_CORE,
10391                                  PROTOCOL_NT1,
10392                                  NULL,
10393                                  NULL,
10394                                  NULL);
10395         if (!NT_STATUS_IS_OK(status)) {
10396                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10397                        nt_errstr(status));
10398                 cli_shutdown(c_dos);
10399                 return False;
10400         }
10401
10402         status = cli_session_setup_anon(c_dos);
10403         if (!NT_STATUS_IS_OK(status)) {
10404                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10405                         host, nt_errstr(status));
10406                 return False;
10407         }
10408
10409         c_nt->map_dos_errors = false;
10410         c_dos->map_dos_errors = false;
10411
10412         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10413                 struct cli_credentials *user_creds = NULL;
10414
10415                 fstr_sprintf(user, "%X", error);
10416
10417                 user_creds = cli_session_creds_init(talloc_tos(),
10418                                                     user,
10419                                                     workgroup,
10420                                                     NULL, /* realm */
10421                                                     password,
10422                                                     false, /* use_kerberos */
10423                                                     false, /* fallback_after_kerberos */
10424                                                     false, /* use_ccache */
10425                                                     false); /* password_is_nt_hash */
10426                 if (user_creds == NULL) {
10427                         printf("cli_session_creds_init(%s) failed\n", user);
10428                         return false;
10429                 }
10430
10431                 status = cli_session_setup_creds(c_nt, user_creds);
10432                 if (NT_STATUS_IS_OK(status)) {
10433                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10434                 }
10435
10436                 /* Case #1: 32-bit NT errors */
10437                 if (!NT_STATUS_IS_DOS(status)) {
10438                         nt_status = status;
10439                 } else {
10440                         printf("/** Dos error on NT connection! (%s) */\n",
10441                                nt_errstr(status));
10442                         nt_status = NT_STATUS(0xc0000000);
10443                 }
10444
10445                 status = cli_session_setup_creds(c_dos, user_creds);
10446                 if (NT_STATUS_IS_OK(status)) {
10447                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10448                 }
10449
10450                 /* Case #1: 32-bit NT errors */
10451                 if (NT_STATUS_IS_DOS(status)) {
10452                         printf("/** NT error on DOS connection! (%s) */\n",
10453                                nt_errstr(status));
10454                         errnum = errclass = 0;
10455                 } else {
10456                         errclass = NT_STATUS_DOS_CLASS(status);
10457                         errnum = NT_STATUS_DOS_CODE(status);
10458                 }
10459
10460                 if (NT_STATUS_V(nt_status) != error) {
10461                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10462                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10463                                get_nt_error_c_code(talloc_tos(), nt_status));
10464                 }
10465
10466                 printf("\t{%s,\t%s,\t%s},\n",
10467                        smb_dos_err_class(errclass),
10468                        smb_dos_err_name(errclass, errnum),
10469                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10470
10471                 TALLOC_FREE(user_creds);
10472         }
10473         return True;
10474 }
10475
10476 static bool run_sesssetup_bench(int dummy)
10477 {
10478         static struct cli_state *c;
10479         const char *fname = "\\file.dat";
10480         uint16_t fnum;
10481         NTSTATUS status;
10482         int i;
10483
10484         if (!torture_open_connection(&c, 0)) {
10485                 return false;
10486         }
10487
10488         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10489                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10490                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10491         if (!NT_STATUS_IS_OK(status)) {
10492                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10493                 return false;
10494         }
10495
10496         for (i=0; i<torture_numops; i++) {
10497                 status = cli_session_setup_creds(c, torture_creds);
10498                 if (!NT_STATUS_IS_OK(status)) {
10499                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10500                                  __location__, nt_errstr(status));
10501                         return false;
10502                 }
10503
10504                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10505
10506                 status = cli_ulogoff(c);
10507                 if (!NT_STATUS_IS_OK(status)) {
10508                         d_printf("(%s) cli_ulogoff failed: %s\n",
10509                                  __location__, nt_errstr(status));
10510                         return false;
10511                 }
10512         }
10513
10514         return true;
10515 }
10516
10517 static bool subst_test(const char *str, const char *user, const char *domain,
10518                        uid_t uid, gid_t gid, const char *expected)
10519 {
10520         char *subst;
10521         bool result = true;
10522
10523         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10524
10525         if (strcmp(subst, expected) != 0) {
10526                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10527                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10528                        expected);
10529                 result = false;
10530         }
10531
10532         TALLOC_FREE(subst);
10533         return result;
10534 }
10535
10536 static void chain1_open_completion(struct tevent_req *req)
10537 {
10538         uint16_t fnum;
10539         NTSTATUS status;
10540         status = cli_openx_recv(req, &fnum);
10541         TALLOC_FREE(req);
10542
10543         d_printf("cli_openx_recv returned %s: %d\n",
10544                  nt_errstr(status),
10545                  NT_STATUS_IS_OK(status) ? fnum : -1);
10546 }
10547
10548 static void chain1_write_completion(struct tevent_req *req)
10549 {
10550         size_t written;
10551         NTSTATUS status;
10552         status = cli_write_andx_recv(req, &written);
10553         TALLOC_FREE(req);
10554
10555         d_printf("cli_write_andx_recv returned %s: %d\n",
10556                  nt_errstr(status),
10557                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10558 }
10559
10560 static void chain1_close_completion(struct tevent_req *req)
10561 {
10562         NTSTATUS status;
10563         bool *done = (bool *)tevent_req_callback_data_void(req);
10564
10565         status = cli_close_recv(req);
10566         *done = true;
10567
10568         TALLOC_FREE(req);
10569
10570         d_printf("cli_close returned %s\n", nt_errstr(status));
10571 }
10572
10573 static bool run_chain1(int dummy)
10574 {
10575         struct cli_state *cli1;
10576         struct tevent_context *evt = samba_tevent_context_init(NULL);
10577         struct tevent_req *reqs[3], *smbreqs[3];
10578         bool done = false;
10579         const char *str = "foobar";
10580         const char *fname = "\\test_chain";
10581         NTSTATUS status;
10582
10583         printf("starting chain1 test\n");
10584         if (!torture_open_connection(&cli1, 0)) {
10585                 return False;
10586         }
10587
10588         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10589
10590         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10591
10592         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10593                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10594         if (reqs[0] == NULL) return false;
10595         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10596
10597
10598         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10599                                         (const uint8_t *)str, 0, strlen(str)+1,
10600                                         smbreqs, 1, &smbreqs[1]);
10601         if (reqs[1] == NULL) return false;
10602         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10603
10604         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10605         if (reqs[2] == NULL) return false;
10606         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10607
10608         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10609         if (!NT_STATUS_IS_OK(status)) {
10610                 return false;
10611         }
10612
10613         while (!done) {
10614                 tevent_loop_once(evt);
10615         }
10616
10617         torture_close_connection(cli1);
10618         return True;
10619 }
10620
10621 static void chain2_sesssetup_completion(struct tevent_req *req)
10622 {
10623         NTSTATUS status;
10624         status = cli_session_setup_guest_recv(req);
10625         d_printf("sesssetup returned %s\n", nt_errstr(status));
10626 }
10627
10628 static void chain2_tcon_completion(struct tevent_req *req)
10629 {
10630         bool *done = (bool *)tevent_req_callback_data_void(req);
10631         NTSTATUS status;
10632         status = cli_tcon_andx_recv(req);
10633         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10634         *done = true;
10635 }
10636
10637 static bool run_chain2(int dummy)
10638 {
10639         struct cli_state *cli1;
10640         struct tevent_context *evt = samba_tevent_context_init(NULL);
10641         struct tevent_req *reqs[2], *smbreqs[2];
10642         bool done = false;
10643         NTSTATUS status;
10644         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10645
10646         printf("starting chain2 test\n");
10647         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10648                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10649         if (!NT_STATUS_IS_OK(status)) {
10650                 return False;
10651         }
10652
10653         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10654
10655         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10656                                                  &smbreqs[0]);
10657         if (reqs[0] == NULL) return false;
10658         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10659
10660         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10661                                        "?????", NULL, 0, &smbreqs[1]);
10662         if (reqs[1] == NULL) return false;
10663         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10664
10665         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10666         if (!NT_STATUS_IS_OK(status)) {
10667                 return false;
10668         }
10669
10670         while (!done) {
10671                 tevent_loop_once(evt);
10672         }
10673
10674         torture_close_connection(cli1);
10675         return True;
10676 }
10677
10678
10679 struct torture_createdel_state {
10680         struct tevent_context *ev;
10681         struct cli_state *cli;
10682 };
10683
10684 static void torture_createdel_created(struct tevent_req *subreq);
10685 static void torture_createdel_closed(struct tevent_req *subreq);
10686
10687 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10688                                                  struct tevent_context *ev,
10689                                                  struct cli_state *cli,
10690                                                  const char *name)
10691 {
10692         struct tevent_req *req, *subreq;
10693         struct torture_createdel_state *state;
10694
10695         req = tevent_req_create(mem_ctx, &state,
10696                                 struct torture_createdel_state);
10697         if (req == NULL) {
10698                 return NULL;
10699         }
10700         state->ev = ev;
10701         state->cli = cli;
10702
10703         subreq = cli_ntcreate_send(
10704                 state, ev, cli, name, 0,
10705                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10706                 FILE_ATTRIBUTE_NORMAL,
10707                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10708                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10709                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10710
10711         if (tevent_req_nomem(subreq, req)) {
10712                 return tevent_req_post(req, ev);
10713         }
10714         tevent_req_set_callback(subreq, torture_createdel_created, req);
10715         return req;
10716 }
10717
10718 static void torture_createdel_created(struct tevent_req *subreq)
10719 {
10720         struct tevent_req *req = tevent_req_callback_data(
10721                 subreq, struct tevent_req);
10722         struct torture_createdel_state *state = tevent_req_data(
10723                 req, struct torture_createdel_state);
10724         NTSTATUS status;
10725         uint16_t fnum;
10726
10727         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10728         TALLOC_FREE(subreq);
10729         if (tevent_req_nterror(req, status)) {
10730                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10731                            nt_errstr(status)));
10732                 return;
10733         }
10734
10735         subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10736         if (tevent_req_nomem(subreq, req)) {
10737                 return;
10738         }
10739         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10740 }
10741
10742 static void torture_createdel_closed(struct tevent_req *subreq)
10743 {
10744         struct tevent_req *req = tevent_req_callback_data(
10745                 subreq, struct tevent_req);
10746         NTSTATUS status;
10747
10748         status = cli_close_recv(subreq);
10749         if (tevent_req_nterror(req, status)) {
10750                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10751                 return;
10752         }
10753         tevent_req_done(req);
10754 }
10755
10756 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10757 {
10758         return tevent_req_simple_recv_ntstatus(req);
10759 }
10760
10761 struct torture_createdels_state {
10762         struct tevent_context *ev;
10763         struct cli_state *cli;
10764         const char *base_name;
10765         int sent;
10766         int received;
10767         int num_files;
10768         struct tevent_req **reqs;
10769 };
10770
10771 static void torture_createdels_done(struct tevent_req *subreq);
10772
10773 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10774                                                   struct tevent_context *ev,
10775                                                   struct cli_state *cli,
10776                                                   const char *base_name,
10777                                                   int num_parallel,
10778                                                   int num_files)
10779 {
10780         struct tevent_req *req;
10781         struct torture_createdels_state *state;
10782         int i;
10783
10784         req = tevent_req_create(mem_ctx, &state,
10785                                 struct torture_createdels_state);
10786         if (req == NULL) {
10787                 return NULL;
10788         }
10789         state->ev = ev;
10790         state->cli = cli;
10791         state->base_name = talloc_strdup(state, base_name);
10792         if (tevent_req_nomem(state->base_name, req)) {
10793                 return tevent_req_post(req, ev);
10794         }
10795         state->num_files = MAX(num_parallel, num_files);
10796         state->sent = 0;
10797         state->received = 0;
10798
10799         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10800         if (tevent_req_nomem(state->reqs, req)) {
10801                 return tevent_req_post(req, ev);
10802         }
10803
10804         for (i=0; i<num_parallel; i++) {
10805                 char *name;
10806
10807                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10808                                        state->sent);
10809                 if (tevent_req_nomem(name, req)) {
10810                         return tevent_req_post(req, ev);
10811                 }
10812                 state->reqs[i] = torture_createdel_send(
10813                         state->reqs, state->ev, state->cli, name);
10814                 if (tevent_req_nomem(state->reqs[i], req)) {
10815                         return tevent_req_post(req, ev);
10816                 }
10817                 name = talloc_move(state->reqs[i], &name);
10818                 tevent_req_set_callback(state->reqs[i],
10819                                         torture_createdels_done, req);
10820                 state->sent += 1;
10821         }
10822         return req;
10823 }
10824
10825 static void torture_createdels_done(struct tevent_req *subreq)
10826 {
10827         struct tevent_req *req = tevent_req_callback_data(
10828                 subreq, struct tevent_req);
10829         struct torture_createdels_state *state = tevent_req_data(
10830                 req, struct torture_createdels_state);
10831         size_t i, num_parallel = talloc_array_length(state->reqs);
10832         NTSTATUS status;
10833         char *name;
10834
10835         status = torture_createdel_recv(subreq);
10836         if (!NT_STATUS_IS_OK(status)){
10837                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10838                            nt_errstr(status)));
10839                 TALLOC_FREE(subreq);
10840                 tevent_req_nterror(req, status);
10841                 return;
10842         }
10843
10844         for (i=0; i<num_parallel; i++) {
10845                 if (subreq == state->reqs[i]) {
10846                         break;
10847                 }
10848         }
10849         if (i == num_parallel) {
10850                 DEBUG(10, ("received something we did not send\n"));
10851                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10852                 return;
10853         }
10854         TALLOC_FREE(state->reqs[i]);
10855
10856         if (state->sent >= state->num_files) {
10857                 tevent_req_done(req);
10858                 return;
10859         }
10860
10861         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10862                                state->sent);
10863         if (tevent_req_nomem(name, req)) {
10864                 return;
10865         }
10866         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10867                                                 state->cli, name);
10868         if (tevent_req_nomem(state->reqs[i], req)) {
10869                 return;
10870         }
10871         name = talloc_move(state->reqs[i], &name);
10872         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10873         state->sent += 1;
10874 }
10875
10876 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10877 {
10878         return tevent_req_simple_recv_ntstatus(req);
10879 }
10880
10881 struct swallow_notify_state {
10882         struct tevent_context *ev;
10883         struct cli_state *cli;
10884         uint16_t fnum;
10885         uint32_t completion_filter;
10886         bool recursive;
10887         bool (*fn)(uint32_t action, const char *name, void *priv);
10888         void *priv;
10889 };
10890
10891 static void swallow_notify_done(struct tevent_req *subreq);
10892
10893 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10894                                               struct tevent_context *ev,
10895                                               struct cli_state *cli,
10896                                               uint16_t fnum,
10897                                               uint32_t completion_filter,
10898                                               bool recursive,
10899                                               bool (*fn)(uint32_t action,
10900                                                          const char *name,
10901                                                          void *priv),
10902                                               void *priv)
10903 {
10904         struct tevent_req *req, *subreq;
10905         struct swallow_notify_state *state;
10906
10907         req = tevent_req_create(mem_ctx, &state,
10908                                 struct swallow_notify_state);
10909         if (req == NULL) {
10910                 return NULL;
10911         }
10912         state->ev = ev;
10913         state->cli = cli;
10914         state->fnum = fnum;
10915         state->completion_filter = completion_filter;
10916         state->recursive = recursive;
10917         state->fn = fn;
10918         state->priv = priv;
10919
10920         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10921                                  0xffff, state->completion_filter,
10922                                  state->recursive);
10923         if (tevent_req_nomem(subreq, req)) {
10924                 return tevent_req_post(req, ev);
10925         }
10926         tevent_req_set_callback(subreq, swallow_notify_done, req);
10927         return req;
10928 }
10929
10930 static void swallow_notify_done(struct tevent_req *subreq)
10931 {
10932         struct tevent_req *req = tevent_req_callback_data(
10933                 subreq, struct tevent_req);
10934         struct swallow_notify_state *state = tevent_req_data(
10935                 req, struct swallow_notify_state);
10936         NTSTATUS status;
10937         uint32_t i, num_changes;
10938         struct notify_change *changes;
10939
10940         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10941         TALLOC_FREE(subreq);
10942         if (!NT_STATUS_IS_OK(status)) {
10943                 DEBUG(10, ("cli_notify_recv returned %s\n",
10944                            nt_errstr(status)));
10945                 tevent_req_nterror(req, status);
10946                 return;
10947         }
10948
10949         for (i=0; i<num_changes; i++) {
10950                 state->fn(changes[i].action, changes[i].name, state->priv);
10951         }
10952         TALLOC_FREE(changes);
10953
10954         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10955                                  0xffff, state->completion_filter,
10956                                  state->recursive);
10957         if (tevent_req_nomem(subreq, req)) {
10958                 return;
10959         }
10960         tevent_req_set_callback(subreq, swallow_notify_done, req);
10961 }
10962
10963 static bool print_notifies(uint32_t action, const char *name, void *priv)
10964 {
10965         if (DEBUGLEVEL > 5) {
10966                 d_printf("%d %s\n", (int)action, name);
10967         }
10968         return true;
10969 }
10970
10971 static void notify_bench_done(struct tevent_req *req)
10972 {
10973         int *num_finished = (int *)tevent_req_callback_data_void(req);
10974         *num_finished += 1;
10975 }
10976
10977 static bool run_notify_bench(int dummy)
10978 {
10979         const char *dname = "\\notify-bench";
10980         struct tevent_context *ev;
10981         NTSTATUS status;
10982         uint16_t dnum;
10983         struct tevent_req *req1;
10984         struct tevent_req *req2 = NULL;
10985         int i, num_unc_names;
10986         int num_finished = 0;
10987
10988         printf("starting notify-bench test\n");
10989
10990         if (use_multishare_conn) {
10991                 char **unc_list;
10992                 unc_list = file_lines_load(multishare_conn_fname,
10993                                            &num_unc_names, 0, NULL);
10994                 if (!unc_list || num_unc_names <= 0) {
10995                         d_printf("Failed to load unc names list from '%s'\n",
10996                                  multishare_conn_fname);
10997                         return false;
10998                 }
10999                 TALLOC_FREE(unc_list);
11000         } else {
11001                 num_unc_names = 1;
11002         }
11003
11004         ev = samba_tevent_context_init(talloc_tos());
11005         if (ev == NULL) {
11006                 d_printf("tevent_context_init failed\n");
11007                 return false;
11008         }
11009
11010         for (i=0; i<num_unc_names; i++) {
11011                 struct cli_state *cli;
11012                 char *base_fname;
11013
11014                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11015                                              dname, i);
11016                 if (base_fname == NULL) {
11017                         return false;
11018                 }
11019
11020                 if (!torture_open_connection(&cli, i)) {
11021                         return false;
11022                 }
11023
11024                 status = cli_ntcreate(cli, dname, 0,
11025                                       MAXIMUM_ALLOWED_ACCESS,
11026                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11027                                       FILE_SHARE_DELETE,
11028                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11029                                       &dnum, NULL);
11030
11031                 if (!NT_STATUS_IS_OK(status)) {
11032                         d_printf("Could not create %s: %s\n", dname,
11033                                  nt_errstr(status));
11034                         return false;
11035                 }
11036
11037                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11038                                            FILE_NOTIFY_CHANGE_FILE_NAME |
11039                                            FILE_NOTIFY_CHANGE_DIR_NAME |
11040                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
11041                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
11042                                            false, print_notifies, NULL);
11043                 if (req1 == NULL) {
11044                         d_printf("Could not create notify request\n");
11045                         return false;
11046                 }
11047
11048                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11049                                                base_fname, 10, torture_numops);
11050                 if (req2 == NULL) {
11051                         d_printf("Could not create createdels request\n");
11052                         return false;
11053                 }
11054                 TALLOC_FREE(base_fname);
11055
11056                 tevent_req_set_callback(req2, notify_bench_done,
11057                                         &num_finished);
11058         }
11059
11060         while (num_finished < num_unc_names) {
11061                 int ret;
11062                 ret = tevent_loop_once(ev);
11063                 if (ret != 0) {
11064                         d_printf("tevent_loop_once failed\n");
11065                         return false;
11066                 }
11067         }
11068
11069         if (!tevent_req_poll(req2, ev)) {
11070                 d_printf("tevent_req_poll failed\n");
11071         }
11072
11073         status = torture_createdels_recv(req2);
11074         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11075
11076         return true;
11077 }
11078
11079 static bool run_mangle1(int dummy)
11080 {
11081         struct cli_state *cli;
11082         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11083         uint16_t fnum;
11084         fstring alt_name;
11085         NTSTATUS status;
11086
11087         printf("starting mangle1 test\n");
11088         if (!torture_open_connection(&cli, 0)) {
11089                 return False;
11090         }
11091
11092         smbXcli_conn_set_sockopt(cli->conn, sockops);
11093
11094         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11095                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11096                               0, 0, &fnum, NULL);
11097         if (!NT_STATUS_IS_OK(status)) {
11098                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11099                 return false;
11100         }
11101         cli_close(cli, fnum);
11102
11103         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11104         if (!NT_STATUS_IS_OK(status)) {
11105                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11106                          nt_errstr(status));
11107                 return false;
11108         }
11109         d_printf("alt_name: %s\n", alt_name);
11110
11111         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11112         if (!NT_STATUS_IS_OK(status)) {
11113                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11114                          nt_errstr(status));
11115                 return false;
11116         }
11117         cli_close(cli, fnum);
11118
11119         status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11120         if (!NT_STATUS_IS_OK(status)) {
11121                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11122                          nt_errstr(status));
11123                 return false;
11124         }
11125
11126         return true;
11127 }
11128
11129 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11130                                                  const char *mask,
11131                                                  void *state)
11132 {
11133         if (f->short_name == NULL) {
11134                 return NT_STATUS_OK;
11135         }
11136
11137         if (strlen(f->short_name) == 0) {
11138                 return NT_STATUS_OK;
11139         }
11140
11141         printf("unexpected shortname: %s\n", f->short_name);
11142
11143         return NT_STATUS_OBJECT_NAME_INVALID;
11144 }
11145
11146 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11147                                             const char *mask,
11148                                             void *state)
11149 {
11150         char *name = state;
11151
11152         printf("name: %s\n", f->name);
11153         fstrcpy(name, f->name);
11154         return NT_STATUS_OK;
11155 }
11156
11157 static bool run_mangle_illegal(int dummy)
11158 {
11159         struct cli_state *cli = NULL;
11160         struct cli_state *cli_posix = NULL;
11161         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11162         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11163         char *mangled_path = NULL;
11164         uint16_t fnum;
11165         fstring name;
11166         fstring alt_name;
11167         NTSTATUS status;
11168
11169         printf("starting mangle-illegal test\n");
11170
11171         if (!torture_open_connection(&cli, 0)) {
11172                 return False;
11173         }
11174
11175         smbXcli_conn_set_sockopt(cli->conn, sockops);
11176
11177         if (!torture_open_connection(&cli_posix, 0)) {
11178                 return false;
11179         }
11180
11181         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11182
11183         status = torture_setup_unix_extensions(cli_posix);
11184         if (!NT_STATUS_IS_OK(status)) {
11185                 return false;
11186         }
11187
11188         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11189         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11190         if (!NT_STATUS_IS_OK(status)) {
11191                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11192                 return False;
11193         }
11194
11195         /*
11196          * Create a file with illegal NTFS characters and test that we
11197          * get a usable mangled name
11198          */
11199
11200         cli_setatr(cli_posix, illegal_fname, 0, 0);
11201         cli_posix_unlink(cli_posix, illegal_fname);
11202
11203         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11204                                 0600, &fnum);
11205         if (!NT_STATUS_IS_OK(status)) {
11206                 printf("POSIX create of %s failed (%s)\n",
11207                        illegal_fname, nt_errstr(status));
11208                 return false;
11209         }
11210
11211         status = cli_close(cli_posix, fnum);
11212         if (!NT_STATUS_IS_OK(status)) {
11213                 printf("close failed (%s)\n", nt_errstr(status));
11214                 return false;
11215         }
11216
11217         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11218         if (!NT_STATUS_IS_OK(status)) {
11219                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11220                 return false;
11221         }
11222
11223         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11224         if (mangled_path == NULL) {
11225                 return false;
11226         }
11227
11228         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11229         if (!NT_STATUS_IS_OK(status)) {
11230                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11231                 TALLOC_FREE(mangled_path);
11232                 return false;
11233         }
11234         TALLOC_FREE(mangled_path);
11235         cli_close(cli, fnum);
11236
11237         cli_setatr(cli_posix, illegal_fname, 0, 0);
11238         cli_posix_unlink(cli_posix, illegal_fname);
11239
11240         /*
11241          * Create a file with a long name and check that we got *no* short name.
11242          */
11243
11244         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11245                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11246                               0, 0, &fnum, NULL);
11247         if (!NT_STATUS_IS_OK(status)) {
11248                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11249                 return false;
11250         }
11251         cli_close(cli, fnum);
11252
11253         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11254         if (!NT_STATUS_IS_OK(status)) {
11255                 d_printf("cli_list failed\n");
11256                 return false;
11257         }
11258
11259         cli_unlink(cli, fname, 0);
11260         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11261
11262         if (!torture_close_connection(cli_posix)) {
11263                 return false;
11264         }
11265
11266         if (!torture_close_connection(cli)) {
11267                 return false;
11268         }
11269
11270         return true;
11271 }
11272
11273 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11274 {
11275         size_t *to_pull = (size_t *)priv;
11276         size_t thistime = *to_pull;
11277
11278         thistime = MIN(thistime, n);
11279         if (thistime == 0) {
11280                 return 0;
11281         }
11282
11283         memset(buf, 0, thistime);
11284         *to_pull -= thistime;
11285         return thistime;
11286 }
11287
11288 static bool run_windows_write(int dummy)
11289 {
11290         struct cli_state *cli1;
11291         uint16_t fnum;
11292         int i;
11293         bool ret = false;
11294         const char *fname = "\\writetest.txt";
11295         struct timeval start_time;
11296         double seconds;
11297         double kbytes;
11298         NTSTATUS status;
11299
11300         printf("starting windows_write test\n");
11301         if (!torture_open_connection(&cli1, 0)) {
11302                 return False;
11303         }
11304
11305         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11306         if (!NT_STATUS_IS_OK(status)) {
11307                 printf("open failed (%s)\n", nt_errstr(status));
11308                 return False;
11309         }
11310
11311         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11312
11313         start_time = timeval_current();
11314
11315         for (i=0; i<torture_numops; i++) {
11316                 uint8_t c = 0;
11317                 off_t start = i * torture_blocksize;
11318                 size_t to_pull = torture_blocksize - 1;
11319
11320                 status = cli_writeall(cli1, fnum, 0, &c,
11321                                       start + torture_blocksize - 1, 1, NULL);
11322                 if (!NT_STATUS_IS_OK(status)) {
11323                         printf("cli_write failed: %s\n", nt_errstr(status));
11324                         goto fail;
11325                 }
11326
11327                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11328                                   null_source, &to_pull);
11329                 if (!NT_STATUS_IS_OK(status)) {
11330                         printf("cli_push returned: %s\n", nt_errstr(status));
11331                         goto fail;
11332                 }
11333         }
11334
11335         seconds = timeval_elapsed(&start_time);
11336         kbytes = (double)torture_blocksize * torture_numops;
11337         kbytes /= 1024;
11338
11339         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11340                (double)seconds, (int)(kbytes/seconds));
11341
11342         ret = true;
11343  fail:
11344         cli_close(cli1, fnum);
11345         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11346         torture_close_connection(cli1);
11347         return ret;
11348 }
11349
11350 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11351 {
11352         size_t max_pdu = 0x1FFFF;
11353
11354         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11355                 max_pdu = 0xFFFFFF;
11356         }
11357
11358         if (smb1cli_conn_signing_is_active(cli->conn)) {
11359                 max_pdu = 0x1FFFF;
11360         }
11361
11362         if (smb1cli_conn_encryption_on(cli->conn)) {
11363                 max_pdu = CLI_BUFFER_SIZE;
11364         }
11365
11366         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11367                 len_requested &= 0xFFFF;
11368         }
11369
11370         return MIN(len_requested,
11371                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11372 }
11373
11374 static bool check_read_call(struct cli_state *cli,
11375                             uint16_t fnum,
11376                             uint8_t *buf,
11377                             size_t len_requested)
11378 {
11379         NTSTATUS status;
11380         struct tevent_req *subreq = NULL;
11381         ssize_t len_read = 0;
11382         size_t len_expected = 0;
11383         struct tevent_context *ev = NULL;
11384
11385         ev = samba_tevent_context_init(talloc_tos());
11386         if (ev == NULL) {
11387                 return false;
11388         }
11389
11390         subreq = cli_read_andx_send(talloc_tos(),
11391                                     ev,
11392                                     cli,
11393                                     fnum,
11394                                     0,
11395                                     len_requested);
11396
11397         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11398                 return false;
11399         }
11400
11401         status = cli_read_andx_recv(subreq, &len_read, &buf);
11402         if (!NT_STATUS_IS_OK(status)) {
11403                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11404                 return false;
11405         }
11406
11407         TALLOC_FREE(subreq);
11408         TALLOC_FREE(ev);
11409
11410         len_expected = calc_expected_return(cli, len_requested);
11411
11412         if (len_expected > 0x10000 && len_read == 0x10000) {
11413                 /* Windows servers only return a max of 0x10000,
11414                    doesn't matter if you set CAP_LARGE_READX in
11415                    the client sessionsetupX call or not. */
11416                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11417                         (unsigned int)len_requested);
11418         } else if (len_read != len_expected) {
11419                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11420                         (unsigned int)len_requested,
11421                         (unsigned int)len_read,
11422                         (unsigned int)len_expected);
11423                 return false;
11424         } else {
11425                 d_printf("Correct read reply.\n");
11426         }
11427
11428         return true;
11429 }
11430
11431 /* Test large readX variants. */
11432 static bool large_readx_tests(struct cli_state *cli,
11433                                 uint16_t fnum,
11434                                 uint8_t *buf)
11435 {
11436         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11437         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11438                 return false;
11439         }
11440         /* A read of 0x10000 should return 0x10000 bytes. */
11441         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11442                 return false;
11443         }
11444         /* A read of 0x10000 should return 0x10001 bytes. */
11445         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11446                 return false;
11447         }
11448         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11449            the requested number of bytes. */
11450         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11451                 return false;
11452         }
11453         /* A read of 1MB should return 1MB bytes (on Samba). */
11454         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11455                 return false;
11456         }
11457
11458         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11459                 return false;
11460         }
11461         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11462                 return false;
11463         }
11464         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11465                 return false;
11466         }
11467         return true;
11468 }
11469
11470 static bool run_large_readx(int dummy)
11471 {
11472         uint8_t *buf = NULL;
11473         struct cli_state *cli1 = NULL;
11474         struct cli_state *cli2 = NULL;
11475         bool correct = false;
11476         const char *fname = "\\large_readx.dat";
11477         NTSTATUS status;
11478         uint16_t fnum1 = UINT16_MAX;
11479         uint32_t normal_caps = 0;
11480         size_t file_size = 20*1024*1024;
11481         TALLOC_CTX *frame = talloc_stackframe();
11482         size_t i;
11483         struct {
11484                 const char *name;
11485                 enum smb_signing_setting signing_setting;
11486                 enum protocol_types protocol;
11487         } runs[] = {
11488                 {
11489                         .name = "NT1",
11490                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11491                         .protocol = PROTOCOL_NT1,
11492                 },{
11493                         .name = "NT1 - SIGNING_REQUIRED",
11494                         .signing_setting = SMB_SIGNING_REQUIRED,
11495                         .protocol = PROTOCOL_NT1,
11496                 },
11497         };
11498
11499         printf("starting large_readx test\n");
11500
11501         if (!torture_open_connection(&cli1, 0)) {
11502                 goto out;
11503         }
11504
11505         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11506
11507         if (!(normal_caps & CAP_LARGE_READX)) {
11508                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11509                         (unsigned int)normal_caps);
11510                 goto out;
11511         }
11512
11513         /* Create a file of size 4MB. */
11514         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11515                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11516                         0, 0, &fnum1, NULL);
11517
11518         if (!NT_STATUS_IS_OK(status)) {
11519                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11520                 goto out;
11521         }
11522
11523         /* Write file_size bytes. */
11524         buf = talloc_zero_array(frame, uint8_t, file_size);
11525         if (buf == NULL) {
11526                 goto out;
11527         }
11528
11529         status = cli_writeall(cli1,
11530                               fnum1,
11531                               0,
11532                               buf,
11533                               0,
11534                               file_size,
11535                               NULL);
11536         if (!NT_STATUS_IS_OK(status)) {
11537                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11538                 goto out;
11539         }
11540
11541         status = cli_close(cli1, fnum1);
11542         if (!NT_STATUS_IS_OK(status)) {
11543                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11544                 goto out;
11545         }
11546
11547         fnum1 = UINT16_MAX;
11548
11549         for (i=0; i < ARRAY_SIZE(runs); i++) {
11550                 enum smb_signing_setting saved_signing_setting = signing_state;
11551                 uint16_t fnum2 = -1;
11552
11553                 if (do_encrypt &&
11554                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11555                 {
11556                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11557                         continue;
11558                 }
11559
11560                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11561
11562                 signing_state = runs[i].signing_setting;
11563                 cli2 = open_nbt_connection();
11564                 signing_state = saved_signing_setting;
11565                 if (cli2 == NULL) {
11566                         goto out;
11567                 }
11568
11569                 status = smbXcli_negprot(cli2->conn,
11570                                          cli2->timeout,
11571                                          runs[i].protocol,
11572                                          runs[i].protocol,
11573                                          NULL,
11574                                          NULL,
11575                                          NULL);
11576                 if (!NT_STATUS_IS_OK(status)) {
11577                         goto out;
11578                 }
11579
11580                 status = cli_session_setup_creds(cli2, torture_creds);
11581                 if (!NT_STATUS_IS_OK(status)) {
11582                         goto out;
11583                 }
11584
11585                 status = cli_tree_connect(cli2,
11586                                         share,
11587                                         "?????",
11588                                         password);
11589                 if (!NT_STATUS_IS_OK(status)) {
11590                         goto out;
11591                 }
11592
11593                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11594
11595                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11596
11597                 if (!(normal_caps & CAP_LARGE_READX)) {
11598                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11599                                 (unsigned int)normal_caps);
11600                         goto out;
11601                 }
11602
11603                 if (do_encrypt) {
11604                         if (force_cli_encryption(cli2, share) == false) {
11605                                 goto out;
11606                         }
11607                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11608                         uint16_t major, minor;
11609                         uint32_t caplow, caphigh;
11610
11611                         status = cli_unix_extensions_version(cli2,
11612                                                              &major, &minor,
11613                                                              &caplow, &caphigh);
11614                         if (!NT_STATUS_IS_OK(status)) {
11615                                 goto out;
11616                         }
11617                 }
11618
11619                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11620                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11621                                 0, 0, &fnum2, NULL);
11622                 if (!NT_STATUS_IS_OK(status)) {
11623                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11624                         goto out;
11625                 }
11626
11627                 /* All reads must return less than file_size bytes. */
11628                 if (!large_readx_tests(cli2, fnum2, buf)) {
11629                         goto out;
11630                 }
11631
11632                 status = cli_close(cli2, fnum2);
11633                 if (!NT_STATUS_IS_OK(status)) {
11634                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11635                         goto out;
11636                 }
11637                 fnum2 = -1;
11638
11639                 if (!torture_close_connection(cli2)) {
11640                         goto out;
11641                 }
11642                 cli2 = NULL;
11643         }
11644
11645         correct = true;
11646         printf("Success on large_readx test\n");
11647
11648   out:
11649
11650         if (cli2) {
11651                 if (!torture_close_connection(cli2)) {
11652                         correct = false;
11653                 }
11654         }
11655
11656         if (cli1) {
11657                 if (fnum1 != UINT16_MAX) {
11658                         status = cli_close(cli1, fnum1);
11659                         if (!NT_STATUS_IS_OK(status)) {
11660                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11661                         }
11662                         fnum1 = UINT16_MAX;
11663                 }
11664
11665                 status = cli_unlink(cli1, fname,
11666                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11667                 if (!NT_STATUS_IS_OK(status)) {
11668                         printf("unlink failed (%s)\n", nt_errstr(status));
11669                 }
11670
11671                 if (!torture_close_connection(cli1)) {
11672                         correct = false;
11673                 }
11674         }
11675
11676         TALLOC_FREE(frame);
11677
11678         printf("finished large_readx test\n");
11679         return correct;
11680 }
11681
11682 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11683                                   const char *mask,
11684                                   void *private_data)
11685 {
11686         uint32_t *p_attr = (uint32_t *)private_data;
11687
11688         if (strequal(finfo->name, test_filename)) {
11689                 *p_attr = finfo->attr;
11690         }
11691
11692         return NT_STATUS_OK;
11693 }
11694
11695 static bool run_msdfs_attribute(int dummy)
11696 {
11697         static struct cli_state *cli;
11698         bool correct = false;
11699         uint32_t attr = 0;
11700         NTSTATUS status;
11701
11702         printf("Starting MSDFS-ATTRIBUTE test\n");
11703
11704         if (test_filename == NULL || test_filename[0] == '\0') {
11705                 printf("MSDFS-ATTRIBUTE test "
11706                         "needs -f filename-of-msdfs-link\n");
11707                 return false;
11708         }
11709
11710         /*
11711          * NB. We use torture_open_connection_flags() not
11712          * torture_open_connection() as the latter forces
11713          * SMB1.
11714          */
11715         if (!torture_open_connection_flags(&cli, 0, 0)) {
11716                 return false;
11717         }
11718
11719         smbXcli_conn_set_sockopt(cli->conn, sockops);
11720
11721         status = cli_list(cli,
11722                         "*",
11723                         FILE_ATTRIBUTE_DIRECTORY,
11724                         msdfs_attribute_list_fn,
11725                         &attr);
11726
11727         if (!NT_STATUS_IS_OK(status)) {
11728                 printf("cli_list failed with %s\n",
11729                         nt_errstr(status));
11730                 goto out;
11731         }
11732         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11733                 printf("file %s should have "
11734                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11735                         test_filename,
11736                         (unsigned int)attr);
11737                 goto out;
11738         }
11739
11740         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11741                 printf("file %s should have "
11742                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11743                         test_filename,
11744                         (unsigned int)attr);
11745                 goto out;
11746         }
11747
11748         correct = true;
11749
11750   out:
11751
11752         torture_close_connection(cli);
11753         return correct;
11754 }
11755
11756 static bool run_cli_echo(int dummy)
11757 {
11758         struct cli_state *cli;
11759         NTSTATUS status;
11760
11761         printf("starting cli_echo test\n");
11762         if (!torture_open_connection(&cli, 0)) {
11763                 return false;
11764         }
11765         smbXcli_conn_set_sockopt(cli->conn, sockops);
11766
11767         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11768
11769         d_printf("cli_echo returned %s\n", nt_errstr(status));
11770
11771         torture_close_connection(cli);
11772         return NT_STATUS_IS_OK(status);
11773 }
11774
11775 static int splice_status(off_t written, void *priv)
11776 {
11777         return true;
11778 }
11779
11780 static bool run_cli_splice(int dummy)
11781 {
11782         uint8_t *buf = NULL;
11783         struct cli_state *cli1 = NULL;
11784         bool correct = false;
11785         const char *fname_src = "\\splice_src.dat";
11786         const char *fname_dst = "\\splice_dst.dat";
11787         NTSTATUS status;
11788         uint16_t fnum1 = UINT16_MAX;
11789         uint16_t fnum2 = UINT16_MAX;
11790         size_t file_size = 2*1024*1024;
11791         size_t splice_size = 1*1024*1024 + 713;
11792         uint8_t digest1[16], digest2[16];
11793         off_t written = 0;
11794         size_t nread = 0;
11795         TALLOC_CTX *frame = talloc_stackframe();
11796
11797         printf("starting cli_splice test\n");
11798
11799         if (!torture_open_connection(&cli1, 0)) {
11800                 goto out;
11801         }
11802
11803         cli_unlink(cli1, fname_src,
11804                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11805         cli_unlink(cli1, fname_dst,
11806                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11807
11808         /* Create a file */
11809         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11810                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11811                         0, 0, &fnum1, NULL);
11812
11813         if (!NT_STATUS_IS_OK(status)) {
11814                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11815                 goto out;
11816         }
11817
11818         /* Write file_size bytes - must be bigger than splice_size. */
11819         buf = talloc_zero_array(frame, uint8_t, file_size);
11820         if (buf == NULL) {
11821                 d_printf("talloc_fail\n");
11822                 goto out;
11823         }
11824
11825         /* Fill it with random numbers. */
11826         generate_random_buffer(buf, file_size);
11827
11828         /* MD5 the first 1MB + 713 bytes. */
11829         gnutls_hash_fast(GNUTLS_DIG_MD5,
11830                          buf,
11831                          splice_size,
11832                          digest1);
11833
11834         status = cli_writeall(cli1,
11835                               fnum1,
11836                               0,
11837                               buf,
11838                               0,
11839                               file_size,
11840                               NULL);
11841         if (!NT_STATUS_IS_OK(status)) {
11842                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11843                 goto out;
11844         }
11845
11846         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11847                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11848                         0, 0, &fnum2, NULL);
11849
11850         if (!NT_STATUS_IS_OK(status)) {
11851                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11852                 goto out;
11853         }
11854
11855         /* Now splice 1MB + 713 bytes. */
11856         status = cli_splice(cli1,
11857                                 cli1,
11858                                 fnum1,
11859                                 fnum2,
11860                                 splice_size,
11861                                 0,
11862                                 0,
11863                                 &written,
11864                                 splice_status,
11865                                 NULL);
11866
11867         if (!NT_STATUS_IS_OK(status)) {
11868                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11869                 goto out;
11870         }
11871
11872         /* Clear the old buffer. */
11873         memset(buf, '\0', file_size);
11874
11875         /* Read the new file. */
11876         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11877         if (!NT_STATUS_IS_OK(status)) {
11878                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11879                 goto out;
11880         }
11881         if (nread != splice_size) {
11882                 d_printf("bad read of 0x%x, should be 0x%x\n",
11883                         (unsigned int)nread,
11884                         (unsigned int)splice_size);
11885                 goto out;
11886         }
11887
11888         /* MD5 the first 1MB + 713 bytes. */
11889         gnutls_hash_fast(GNUTLS_DIG_MD5,
11890                          buf,
11891                          splice_size,
11892                          digest2);
11893
11894         /* Must be the same. */
11895         if (memcmp(digest1, digest2, 16) != 0) {
11896                 d_printf("bad MD5 compare\n");
11897                 goto out;
11898         }
11899
11900         correct = true;
11901         printf("Success on cli_splice test\n");
11902
11903   out:
11904
11905         if (cli1) {
11906                 if (fnum1 != UINT16_MAX) {
11907                         cli_close(cli1, fnum1);
11908                 }
11909                 if (fnum2 != UINT16_MAX) {
11910                         cli_close(cli1, fnum2);
11911                 }
11912
11913                 cli_unlink(cli1, fname_src,
11914                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11915                 cli_unlink(cli1, fname_dst,
11916                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11917
11918                 if (!torture_close_connection(cli1)) {
11919                         correct = false;
11920                 }
11921         }
11922
11923         TALLOC_FREE(frame);
11924         return correct;
11925 }
11926
11927 static bool run_uid_regression_test(int dummy)
11928 {
11929         static struct cli_state *cli;
11930         int16_t old_vuid;
11931         int32_t old_cnum;
11932         bool correct = True;
11933         struct smbXcli_tcon *tcon_copy = NULL;
11934         NTSTATUS status;
11935
11936         printf("starting uid regression test\n");
11937
11938         if (!torture_open_connection(&cli, 0)) {
11939                 return False;
11940         }
11941
11942         smbXcli_conn_set_sockopt(cli->conn, sockops);
11943
11944         /* Ok - now save then logoff our current user. */
11945         old_vuid = cli_state_get_uid(cli);
11946
11947         status = cli_ulogoff(cli);
11948         if (!NT_STATUS_IS_OK(status)) {
11949                 d_printf("(%s) cli_ulogoff failed: %s\n",
11950                          __location__, nt_errstr(status));
11951                 correct = false;
11952                 goto out;
11953         }
11954
11955         cli_state_set_uid(cli, old_vuid);
11956
11957         /* Try an operation. */
11958         status = cli_mkdir(cli, "\\uid_reg_test");
11959         if (NT_STATUS_IS_OK(status)) {
11960                 d_printf("(%s) cli_mkdir succeeded\n",
11961                          __location__);
11962                 correct = false;
11963                 goto out;
11964         } else {
11965                 /* Should be bad uid. */
11966                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11967                                  NT_STATUS_USER_SESSION_DELETED)) {
11968                         correct = false;
11969                         goto out;
11970                 }
11971         }
11972
11973         old_cnum = cli_state_get_tid(cli);
11974         /*
11975          * This is an SMB1-only test.
11976          * Copy the tcon, not "save/restore".
11977          *
11978          * In SMB1 the cli_tdis() below frees
11979          * cli->smb1.tcon so we need a copy
11980          * of the struct to put back for the
11981          * second tdis call with invalid vuid.
11982          *
11983          * This is a test-only hack. Real client code
11984          * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11985          */
11986         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11987         if (tcon_copy == NULL) {
11988                 correct = false;
11989                 goto out;
11990         }
11991
11992         /* Now try a SMBtdis with the invalid vuid set to zero. */
11993         cli_state_set_uid(cli, 0);
11994
11995         /* This should succeed. */
11996         status = cli_tdis(cli);
11997
11998         if (NT_STATUS_IS_OK(status)) {
11999                 d_printf("First tdis with invalid vuid should succeed.\n");
12000         } else {
12001                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
12002                 correct = false;
12003                 cli->smb1.tcon = tcon_copy;
12004                 goto out;
12005         }
12006
12007         cli->smb1.tcon = tcon_copy;
12008         cli_state_set_uid(cli, old_vuid);
12009         cli_state_set_tid(cli, old_cnum);
12010
12011         /* This should fail. */
12012         status = cli_tdis(cli);
12013         if (NT_STATUS_IS_OK(status)) {
12014                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12015                 correct = false;
12016                 goto out;
12017         } else {
12018                 /* Should be bad tid. */
12019                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12020                                 NT_STATUS_NETWORK_NAME_DELETED)) {
12021                         correct = false;
12022                         goto out;
12023                 }
12024         }
12025
12026         cli_rmdir(cli, "\\uid_reg_test");
12027
12028   out:
12029
12030         cli_shutdown(cli);
12031         return correct;
12032 }
12033
12034
12035 static const char *illegal_chars = "*\\/?<>|\":";
12036 static char force_shortname_chars[] = " +,.[];=\177";
12037
12038 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12039                              const char *mask, void *state)
12040 {
12041         struct cli_state *pcli = (struct cli_state *)state;
12042         fstring fname;
12043         NTSTATUS status = NT_STATUS_OK;
12044
12045         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12046
12047         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12048                 return NT_STATUS_OK;
12049
12050         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12051                 status = cli_rmdir(pcli, fname);
12052                 if (!NT_STATUS_IS_OK(status)) {
12053                         printf("del_fn: failed to rmdir %s\n,", fname );
12054                 }
12055         } else {
12056                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12057                 if (!NT_STATUS_IS_OK(status)) {
12058                         printf("del_fn: failed to unlink %s\n,", fname );
12059                 }
12060         }
12061         return status;
12062 }
12063
12064 struct sn_state {
12065         int matched;
12066         int i;
12067         bool val;
12068 };
12069
12070 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12071                               const char *name, void *state)
12072 {
12073         struct sn_state *s = (struct sn_state  *)state;
12074         int i = s->i;
12075
12076 #if 0
12077         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12078                 i, finfo->name, finfo->short_name);
12079 #endif
12080
12081         if (strchr(force_shortname_chars, i)) {
12082                 if (!finfo->short_name) {
12083                         /* Shortname not created when it should be. */
12084                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12085                                 __location__, finfo->name, i);
12086                         s->val = true;
12087                 }
12088         } else if (finfo->short_name){
12089                 /* Shortname created when it should not be. */
12090                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12091                         __location__, finfo->short_name, finfo->name);
12092                 s->val = true;
12093         }
12094         s->matched += 1;
12095         return NT_STATUS_OK;
12096 }
12097
12098 static bool run_shortname_test(int dummy)
12099 {
12100         static struct cli_state *cli;
12101         bool correct = True;
12102         int i;
12103         struct sn_state s;
12104         char fname[40];
12105         NTSTATUS status;
12106
12107         printf("starting shortname test\n");
12108
12109         if (!torture_open_connection(&cli, 0)) {
12110                 return False;
12111         }
12112
12113         smbXcli_conn_set_sockopt(cli->conn, sockops);
12114
12115         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12116         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12117         cli_rmdir(cli, "\\shortname");
12118
12119         status = cli_mkdir(cli, "\\shortname");
12120         if (!NT_STATUS_IS_OK(status)) {
12121                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12122                         __location__, nt_errstr(status));
12123                 correct = false;
12124                 goto out;
12125         }
12126
12127         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12128                 correct = false;
12129                 goto out;
12130         }
12131         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12132                 correct = false;
12133                 goto out;
12134         }
12135
12136         s.val = false;
12137
12138         for (i = 32; i < 128; i++) {
12139                 uint16_t fnum = (uint16_t)-1;
12140
12141                 s.i = i;
12142
12143                 if (strchr(illegal_chars, i)) {
12144                         continue;
12145                 }
12146                 fname[15] = i;
12147
12148                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12149                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12150                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12151                 if (!NT_STATUS_IS_OK(status)) {
12152                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12153                                 __location__, fname, nt_errstr(status));
12154                         correct = false;
12155                         goto out;
12156                 }
12157                 cli_close(cli, fnum);
12158
12159                 s.matched = 0;
12160                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12161                                   shortname_list_fn, &s);
12162                 if (s.matched != 1) {
12163                         d_printf("(%s) failed to list %s: %s\n",
12164                                 __location__, fname, nt_errstr(status));
12165                         correct = false;
12166                         goto out;
12167                 }
12168
12169                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12170                 if (!NT_STATUS_IS_OK(status)) {
12171                         d_printf("(%s) failed to delete %s: %s\n",
12172                                 __location__, fname, nt_errstr(status));
12173                         correct = false;
12174                         goto out;
12175                 }
12176
12177                 if (s.val) {
12178                         correct = false;
12179                         goto out;
12180                 }
12181         }
12182
12183   out:
12184
12185         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12186         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12187         cli_rmdir(cli, "\\shortname");
12188         torture_close_connection(cli);
12189         return correct;
12190 }
12191
12192 TLDAPRC callback_code;
12193
12194 static void pagedsearch_cb(struct tevent_req *req)
12195 {
12196         TLDAPRC rc;
12197         struct tldap_message *msg;
12198         char *dn;
12199
12200         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12201         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12202                 d_printf("tldap_search_paged_recv failed: %s\n",
12203                          tldap_rc2string(rc));
12204                 callback_code = rc;
12205                 return;
12206         }
12207         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12208                 TALLOC_FREE(msg);
12209                 return;
12210         }
12211         if (!tldap_entry_dn(msg, &dn)) {
12212                 d_printf("tldap_entry_dn failed\n");
12213                 return;
12214         }
12215         d_printf("%s\n", dn);
12216         TALLOC_FREE(msg);
12217 }
12218
12219 enum tldap_extended_val {
12220         EXTENDED_ZERO = 0,
12221         EXTENDED_ONE = 1,
12222         EXTENDED_NONE = 2,
12223 };
12224
12225 /*
12226  * Construct an extended dn control with either no value, 0 or 1
12227  *
12228  * No value and 0 are equivalent (non-hyphenated GUID)
12229  * 1 has the hyphenated GUID
12230  */
12231 static struct tldap_control *
12232 tldap_build_extended_control(enum tldap_extended_val val)
12233 {
12234         struct tldap_control empty_control;
12235         struct asn1_data *data;
12236
12237         ZERO_STRUCT(empty_control);
12238
12239         if (val != EXTENDED_NONE) {
12240                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12241
12242                 if (!data) {
12243                         return NULL;
12244                 }
12245
12246                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12247                         return NULL;
12248                 }
12249
12250                 if (!asn1_write_Integer(data, (int)val)) {
12251                         return NULL;
12252                 }
12253
12254                 if (!asn1_pop_tag(data)) {
12255                         return NULL;
12256                 }
12257
12258                 if (!asn1_blob(data, &empty_control.value)) {
12259                         return NULL;
12260                 }
12261         }
12262
12263         empty_control.oid = "1.2.840.113556.1.4.529";
12264         empty_control.critical = true;
12265
12266         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12267
12268 }
12269
12270 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12271                                       enum tldap_extended_val control_val)
12272 {
12273         struct tldap_control *control = tldap_build_extended_control(control_val);
12274         char *dn = NULL;
12275         struct tldap_message **msg;
12276         TLDAPRC rc;
12277
12278         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12279                           "(objectClass=*)", NULL, 0, 0,
12280                           control, 1, NULL,
12281                           0, 0, 0, 0, talloc_tos(), &msg);
12282         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12283                 d_printf("tldap_search for domain DN failed: %s\n",
12284                          tldap_errstr(talloc_tos(), ld, rc));
12285                 return false;
12286         }
12287
12288         if (!tldap_entry_dn(msg[0], &dn)) {
12289                 d_printf("tldap_search domain DN fetch failed: %s\n",
12290                          tldap_errstr(talloc_tos(), ld, rc));
12291                 return false;
12292         }
12293
12294         d_printf("%s\n", dn);
12295         {
12296                 uint32_t time_low;
12297                 uint32_t time_mid, time_hi_and_version;
12298                 uint32_t clock_seq[2];
12299                 uint32_t node[6];
12300                 char next;
12301
12302                 switch (control_val) {
12303                 case EXTENDED_NONE:
12304                 case EXTENDED_ZERO:
12305                         /*
12306                          * When reading GUIDs with hyphens, scanf will treat
12307                          * hyphen as a hex character (and counts as part of the
12308                          * width). This creates leftover GUID string which we
12309                          * check will for with 'next' and closing '>'.
12310                          */
12311                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12312                                          &time_low, &time_mid,
12313                                          &time_hi_and_version, &clock_seq[0],
12314                                          &clock_seq[1], &node[0], &node[1],
12315                                          &node[2], &node[3], &node[4],
12316                                          &node[5], &next)) {
12317                                 /* This GUID is good */
12318                         } else {
12319                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12320                                 return false;
12321                         }
12322
12323                         break;
12324                 case EXTENDED_ONE:
12325                         if (12 == sscanf(dn,
12326                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12327                                          &time_low, &time_mid,
12328                                          &time_hi_and_version, &clock_seq[0],
12329                                          &clock_seq[1], &node[0], &node[1],
12330                                          &node[2], &node[3], &node[4],
12331                                          &node[5], &next)) {
12332                                 /* This GUID is good */
12333                         } else {
12334                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12335                                 return false;
12336                         }
12337
12338                         break;
12339                 default:
12340                         return false;
12341                 }
12342         }
12343
12344         return true;
12345 }
12346
12347 static bool run_tldap(int dummy)
12348 {
12349         struct tldap_context *ld;
12350         int fd;
12351         TLDAPRC rc;
12352         NTSTATUS status;
12353         struct sockaddr_storage addr;
12354         struct tevent_context *ev;
12355         struct tevent_req *req;
12356         char *basedn;
12357         const char *filter;
12358         struct loadparm_context *lp_ctx = NULL;
12359         int tcp_port = 389;
12360         bool use_tls = false;
12361         bool use_starttls = false;
12362         int wrap_flags = -1;
12363         uint32_t gensec_features = 0;
12364
12365         lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12366
12367         wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12368
12369         if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12370                 use_tls = true;
12371                 tcp_port = 636;
12372         } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12373                 use_tls = true;
12374                 use_starttls = true;
12375         }
12376         if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12377                 gensec_features |= GENSEC_FEATURE_SEAL;
12378         }
12379         if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12380                 gensec_features |= GENSEC_FEATURE_SIGN;
12381         }
12382
12383         if (gensec_features != 0) {
12384                 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12385         }
12386
12387         if (!resolve_name(host, &addr, 0, false)) {
12388                 d_printf("could not find host %s\n", host);
12389                 return false;
12390         }
12391         status = open_socket_out(&addr, tcp_port, 9999, &fd);
12392         if (!NT_STATUS_IS_OK(status)) {
12393                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12394                 return false;
12395         }
12396
12397         ld = tldap_context_create(talloc_tos(), fd);
12398         if (ld == NULL) {
12399                 close(fd);
12400                 d_printf("tldap_context_create failed\n");
12401                 return false;
12402         }
12403
12404         if (use_tls && !tldap_has_tls_tstream(ld)) {
12405                 tldap_set_starttls_needed(ld, use_starttls);
12406
12407                 rc = tldap_tls_connect(ld, lp_ctx, host);
12408                 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12409                         DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12410                                 host, tldap_errstr(talloc_tos(), ld, rc));
12411                         return false;
12412                 }
12413         }
12414
12415         rc = tldap_fetch_rootdse(ld);
12416         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12417                 d_printf("tldap_fetch_rootdse failed: %s\n",
12418                          tldap_errstr(talloc_tos(), ld, rc));
12419                 return false;
12420         }
12421
12422         basedn = tldap_talloc_single_attribute(
12423                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12424         if (basedn == NULL) {
12425                 d_printf("no defaultNamingContext\n");
12426                 return false;
12427         }
12428         d_printf("defaultNamingContext: %s\n", basedn);
12429
12430         ev = samba_tevent_context_init(talloc_tos());
12431         if (ev == NULL) {
12432                 d_printf("tevent_context_init failed\n");
12433                 return false;
12434         }
12435
12436         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12437                                lp_ctx, gensec_features);
12438         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12439                 d_printf("tldap_gensec_bind failed\n");
12440                 return false;
12441         }
12442
12443         callback_code = TLDAP_SUCCESS;
12444
12445         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12446                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12447                                       NULL, 0, 0,
12448                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12449         if (req == NULL) {
12450                 d_printf("tldap_search_paged_send failed\n");
12451                 return false;
12452         }
12453         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12454
12455         tevent_req_poll(req, ev);
12456
12457         TALLOC_FREE(req);
12458
12459         rc = callback_code;
12460
12461         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12462                 d_printf("tldap_search with paging failed: %s\n",
12463                          tldap_errstr(talloc_tos(), ld, rc));
12464                 return false;
12465         }
12466
12467         /* test search filters against rootDSE */
12468         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12469                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12470
12471         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12472                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12473                           talloc_tos(), NULL);
12474         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12475                 d_printf("tldap_search with complex filter failed: %s\n",
12476                          tldap_errstr(talloc_tos(), ld, rc));
12477                 return false;
12478         }
12479
12480         /*
12481          * Tests to check for regression of:
12482          *
12483          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12484          *
12485          * TLDAP used here to pick apart the original string DN (with GUID)
12486          */
12487         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12488                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12489                          tldap_errstr(talloc_tos(), ld, rc));
12490                 return false;
12491         }
12492         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12493                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12494                          tldap_errstr(talloc_tos(), ld, rc));
12495                 return false;
12496         }
12497         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12498                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12499                          tldap_errstr(talloc_tos(), ld, rc));
12500                 return false;
12501         }
12502
12503         TALLOC_FREE(ld);
12504         return true;
12505 }
12506
12507 /* Torture test to ensure no regression of :
12508 https://bugzilla.samba.org/show_bug.cgi?id=7084
12509 */
12510
12511 static bool run_dir_createtime(int dummy)
12512 {
12513         struct cli_state *cli;
12514         const char *dname = "\\testdir_createtime";
12515         const char *fname = "\\testdir_createtime\\testfile";
12516         NTSTATUS status;
12517         struct timespec create_time;
12518         struct timespec create_time1;
12519         uint16_t fnum;
12520         bool ret = false;
12521         uint64_t ino;
12522
12523         if (!torture_open_connection(&cli, 0)) {
12524                 return false;
12525         }
12526
12527         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12528                 /* Ensure ino is zero, SMB2 gets a real one. */
12529                 ino = 0;
12530         } else {
12531                 /* Ensure ino is -1, SMB1 never gets a real one. */
12532                 ino = (uint64_t)-1;
12533         }
12534
12535         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12536         cli_rmdir(cli, dname);
12537
12538         status = cli_mkdir(cli, dname);
12539         if (!NT_STATUS_IS_OK(status)) {
12540                 printf("mkdir failed: %s\n", nt_errstr(status));
12541                 goto out;
12542         }
12543
12544         status = cli_qpathinfo2(cli,
12545                                 dname,
12546                                 &create_time,
12547                                 NULL,
12548                                 NULL,
12549                                 NULL,
12550                                 NULL,
12551                                 NULL,
12552                                 &ino,
12553                                 NULL);
12554         if (!NT_STATUS_IS_OK(status)) {
12555                 printf("cli_qpathinfo2 returned %s\n",
12556                        nt_errstr(status));
12557                 goto out;
12558         }
12559
12560         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12561                 /* SMB2 should always return an inode. */
12562                 if (ino == 0) {
12563                         printf("SMB2 bad inode (0)\n");
12564                         goto out;
12565                 }
12566         } else {
12567                 /* SMB1 must always return zero here. */
12568                 if (ino != 0) {
12569                         printf("SMB1 bad inode (!0)\n");
12570                         goto out;
12571                 }
12572         }
12573
12574         /* Sleep 3 seconds, then create a file. */
12575         sleep(3);
12576
12577         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12578                          DENY_NONE, &fnum);
12579         if (!NT_STATUS_IS_OK(status)) {
12580                 printf("cli_openx failed: %s\n", nt_errstr(status));
12581                 goto out;
12582         }
12583
12584         status = cli_qpathinfo2(cli,
12585                                 dname,
12586                                 &create_time1,
12587                                 NULL,
12588                                 NULL,
12589                                 NULL,
12590                                 NULL,
12591                                 NULL,
12592                                 NULL,
12593                                 NULL);
12594         if (!NT_STATUS_IS_OK(status)) {
12595                 printf("cli_qpathinfo2 (2) returned %s\n",
12596                        nt_errstr(status));
12597                 goto out;
12598         }
12599
12600         if (timespec_compare(&create_time1, &create_time)) {
12601                 printf("run_dir_createtime: create time was updated (error)\n");
12602         } else {
12603                 printf("run_dir_createtime: create time was not updated (correct)\n");
12604                 ret = true;
12605         }
12606
12607   out:
12608
12609         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12610         cli_rmdir(cli, dname);
12611         if (!torture_close_connection(cli)) {
12612                 ret = false;
12613         }
12614         return ret;
12615 }
12616
12617
12618 static bool run_streamerror(int dummy)
12619 {
12620         struct cli_state *cli;
12621         const char *dname = "\\testdir_streamerror";
12622         const char *streamname =
12623                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12624         NTSTATUS status;
12625         time_t change_time, access_time, write_time;
12626         off_t size;
12627         uint16_t fnum;
12628         uint32_t attr;
12629         bool ret = true;
12630
12631         if (!torture_open_connection(&cli, 0)) {
12632                 return false;
12633         }
12634
12635         torture_deltree(cli, dname);
12636
12637         status = cli_mkdir(cli, dname);
12638         if (!NT_STATUS_IS_OK(status)) {
12639                 printf("mkdir failed: %s\n", nt_errstr(status));
12640                 return false;
12641         }
12642
12643         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12644                                 &write_time, &size, &attr);
12645         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12646                 printf("pathinfo returned %s, expected "
12647                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12648                        nt_errstr(status));
12649                 ret = false;
12650         }
12651
12652         status = cli_ntcreate(cli, streamname, 0x16,
12653                               FILE_READ_DATA|FILE_READ_EA|
12654                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12655                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12656                               FILE_OPEN, 0, 0, &fnum, NULL);
12657
12658         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12659                 printf("ntcreate returned %s, expected "
12660                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12661                        nt_errstr(status));
12662                 ret = false;
12663         }
12664
12665
12666         cli_rmdir(cli, dname);
12667         return ret;
12668 }
12669
12670 struct pidtest_state {
12671         bool success;
12672         uint16_t vwv[1];
12673         DATA_BLOB data;
12674 };
12675
12676 static void pid_echo_done(struct tevent_req *subreq);
12677
12678 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12679                         struct tevent_context *ev,
12680                         struct cli_state *cli)
12681 {
12682         struct tevent_req *req, *subreq;
12683         struct pidtest_state *state;
12684
12685         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12686         if (req == NULL) {
12687                 return NULL;
12688         }
12689
12690         SSVAL(state->vwv, 0, 1);
12691         state->data = data_blob_const("hello", 5);
12692
12693         subreq = smb1cli_req_send(state,
12694                                 ev,
12695                                 cli->conn,
12696                                 SMBecho,
12697                                 0, 0, /* *_flags */
12698                                 0, 0, /* *_flags2 */
12699                                 cli->timeout,
12700                                 0xDEADBEEF, /* pid */
12701                                 NULL, /* tcon */
12702                                 NULL, /* session */
12703                                 ARRAY_SIZE(state->vwv), state->vwv,
12704                                 state->data.length, state->data.data);
12705
12706         if (tevent_req_nomem(subreq, req)) {
12707                 return tevent_req_post(req, ev);
12708         }
12709         tevent_req_set_callback(subreq, pid_echo_done, req);
12710         return req;
12711 }
12712
12713 static void pid_echo_done(struct tevent_req *subreq)
12714 {
12715         struct tevent_req *req = tevent_req_callback_data(
12716                 subreq, struct tevent_req);
12717         struct pidtest_state *state = tevent_req_data(
12718                 req, struct pidtest_state);
12719         NTSTATUS status;
12720         uint32_t num_bytes;
12721         uint8_t *bytes = NULL;
12722         struct iovec *recv_iov = NULL;
12723         uint8_t *phdr = NULL;
12724         uint16_t pidlow = 0;
12725         uint16_t pidhigh = 0;
12726         struct smb1cli_req_expected_response expected[] = {
12727         {
12728                 .status = NT_STATUS_OK,
12729                 .wct    = 1,
12730         },
12731         };
12732
12733         status = smb1cli_req_recv(subreq, state,
12734                                 &recv_iov,
12735                                 &phdr,
12736                                 NULL, /* pwct */
12737                                 NULL, /* pvwv */
12738                                 NULL, /* pvwv_offset */
12739                                 &num_bytes,
12740                                 &bytes,
12741                                 NULL, /* pbytes_offset */
12742                                 NULL, /* pinbuf */
12743                                 expected, ARRAY_SIZE(expected));
12744
12745         TALLOC_FREE(subreq);
12746
12747         if (!NT_STATUS_IS_OK(status)) {
12748                 tevent_req_nterror(req, status);
12749                 return;
12750         }
12751
12752         if (num_bytes != state->data.length) {
12753                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12754                 return;
12755         }
12756
12757         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12758                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12759                 return;
12760         }
12761
12762         /* Check pid low/high == DEADBEEF */
12763         pidlow = SVAL(phdr, HDR_PID);
12764         if (pidlow != 0xBEEF){
12765                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12766                         (unsigned int)pidlow);
12767                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12768                 return;
12769         }
12770         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12771         if (pidhigh != 0xDEAD){
12772                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12773                         (unsigned int)pidhigh);
12774                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12775                 return;
12776         }
12777
12778         tevent_req_done(req);
12779 }
12780
12781 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12782 {
12783         return tevent_req_simple_recv_ntstatus(req);
12784 }
12785
12786 static bool run_pidhigh(int dummy)
12787 {
12788         bool success = false;
12789         struct cli_state *cli = NULL;
12790         NTSTATUS status;
12791         struct tevent_context *ev = NULL;
12792         struct tevent_req *req = NULL;
12793         TALLOC_CTX *frame = talloc_stackframe();
12794
12795         printf("starting pid high test\n");
12796         if (!torture_open_connection(&cli, 0)) {
12797                 return false;
12798         }
12799         smbXcli_conn_set_sockopt(cli->conn, sockops);
12800
12801         ev = samba_tevent_context_init(frame);
12802         if (ev == NULL) {
12803                 goto fail;
12804         }
12805
12806         req = pid_echo_send(frame, ev, cli);
12807         if (req == NULL) {
12808                 goto fail;
12809         }
12810
12811         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12812                 goto fail;
12813         }
12814
12815         status = pid_echo_recv(req);
12816         if (NT_STATUS_IS_OK(status)) {
12817                 printf("pid high test ok\n");
12818                 success = true;
12819         }
12820
12821  fail:
12822
12823         TALLOC_FREE(frame);
12824         torture_close_connection(cli);
12825         return success;
12826 }
12827
12828 /*
12829   Test Windows open on a bad POSIX symlink.
12830  */
12831 static bool run_symlink_open_test(int dummy)
12832 {
12833         static struct cli_state *cli;
12834         const char *fname = "non_existant_file";
12835         const char *sname = "dangling_symlink";
12836         uint16_t fnum = (uint16_t)-1;
12837         bool correct = false;
12838         NTSTATUS status;
12839         TALLOC_CTX *frame = NULL;
12840
12841         frame = talloc_stackframe();
12842
12843         printf("Starting Windows bad symlink open test\n");
12844
12845         if (!torture_open_connection(&cli, 0)) {
12846                 TALLOC_FREE(frame);
12847                 return false;
12848         }
12849
12850         smbXcli_conn_set_sockopt(cli->conn, sockops);
12851
12852         status = torture_setup_unix_extensions(cli);
12853         if (!NT_STATUS_IS_OK(status)) {
12854                 TALLOC_FREE(frame);
12855                 return false;
12856         }
12857
12858         /* Ensure nothing exists. */
12859         cli_setatr(cli, fname, 0, 0);
12860         cli_posix_unlink(cli, fname);
12861         cli_setatr(cli, sname, 0, 0);
12862         cli_posix_unlink(cli, sname);
12863
12864         /* Create a symlink pointing nowhere. */
12865         status = cli_posix_symlink(cli, fname, sname);
12866         if (!NT_STATUS_IS_OK(status)) {
12867                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12868                         sname,
12869                         fname,
12870                         nt_errstr(status));
12871                 goto out;
12872         }
12873
12874         /* Now ensure that a Windows open doesn't hang. */
12875         status = cli_ntcreate(cli,
12876                         sname,
12877                         0,
12878                         FILE_READ_DATA|FILE_WRITE_DATA,
12879                         0,
12880                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12881                         FILE_OPEN_IF,
12882                         0x0,
12883                         0x0,
12884                         &fnum,
12885                         NULL);
12886
12887         /*
12888          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12889          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12890          * we use O_NOFOLLOW on the server or not.
12891          */
12892         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12893             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12894         {
12895                 correct = true;
12896         } else {
12897                 printf("cli_ntcreate of %s returned %s - should return"
12898                                 " either (%s) or (%s)\n",
12899                         sname,
12900                         nt_errstr(status),
12901                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12902                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12903                 goto out;
12904         }
12905
12906         correct = true;
12907
12908   out:
12909
12910         if (fnum != (uint16_t)-1) {
12911                 cli_close(cli, fnum);
12912                 fnum = (uint16_t)-1;
12913         }
12914
12915         cli_setatr(cli, sname, 0, 0);
12916         cli_posix_unlink(cli, sname);
12917         cli_setatr(cli, fname, 0, 0);
12918         cli_posix_unlink(cli, fname);
12919
12920         if (!torture_close_connection(cli)) {
12921                 correct = false;
12922         }
12923
12924         TALLOC_FREE(frame);
12925         return correct;
12926 }
12927
12928 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12929                                         const char *name,
12930                                         void *state)
12931 {
12932         char **mangled_name_return = (char **)state;
12933         bool is_mangled = strchr(finfo->name, '~');
12934
12935         if (is_mangled) {
12936                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12937                 if (*mangled_name_return == NULL) {
12938                         return NT_STATUS_NO_MEMORY;
12939                 }
12940         }
12941         return NT_STATUS_OK;
12942 }
12943
12944 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12945 {
12946         static struct cli_state *cli_posix = NULL;
12947         static struct cli_state *cli = NULL;
12948         uint16_t fnum = (uint16_t)-1;
12949         bool correct = false;
12950         const char *dname = "smb1_wild_mangle_unlink";
12951         const char *aname = "smb1_wild_mangle_unlink/a";
12952         const char *star_name = "smb1_wild_mangle_unlink/*";
12953         char *windows_unlink_name = NULL;
12954         char *mangled_name = NULL;
12955         NTSTATUS status;
12956
12957         printf("Starting SMB1 wild mangle unlink test\n");
12958
12959         /* Open a Windows connection. */
12960         if (!torture_open_connection(&cli, 0)) {
12961                 return false;
12962         }
12963
12964         smbXcli_conn_set_sockopt(cli->conn, sockops);
12965
12966         /* Open a POSIX connection. */
12967         if (!torture_open_connection(&cli_posix, 0)) {
12968                 goto out;
12969         }
12970
12971         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12972
12973         status = torture_setup_unix_extensions(cli_posix);
12974         if (!NT_STATUS_IS_OK(status)) {
12975                 printf("server doesn't support POSIX\n");
12976                 goto out;
12977         }
12978
12979         /* Start fresh. */
12980         torture_deltree(cli, dname);
12981
12982         /*
12983          * Create two files - 'a' and '*'.
12984          * We need POSIX extensions for this as '*'
12985          * is not a valid Windows name.
12986          */
12987
12988         status = cli_mkdir(cli, dname);
12989         if (!NT_STATUS_IS_OK(status)) {
12990                 printf("cli_mkdir of %s returned %s\n",
12991                         dname,
12992                         nt_errstr(status));
12993                 goto out;
12994         }
12995
12996         status = cli_posix_open(cli_posix,
12997                                 aname,
12998                                 O_RDWR|O_CREAT|O_EXCL,
12999                                 0660,
13000                                 &fnum);
13001         if (!NT_STATUS_IS_OK(status)) {
13002                 printf("cli_posix_open (create) of %s returned %s\n",
13003                         aname,
13004                         nt_errstr(status));
13005                 goto out;
13006         }
13007         status = cli_close(cli_posix, fnum);
13008         if (!NT_STATUS_IS_OK(status)) {
13009                 goto out;
13010         }
13011         status = cli_posix_open(cli_posix,
13012                                 star_name,
13013                                 O_RDWR|O_CREAT|O_EXCL,
13014                                 0660,
13015                                 &fnum);
13016         if (!NT_STATUS_IS_OK(status)) {
13017                 printf("cli_posix_open (create) of %s returned %s\n",
13018                         star_name,
13019                         nt_errstr(status));
13020                 goto out;
13021         }
13022         status = cli_close(cli_posix, fnum);
13023         if (!NT_STATUS_IS_OK(status)) {
13024                 goto out;
13025         }
13026
13027         status = cli_list(cli,
13028                         star_name,
13029                         0,
13030                         smb1_wild_mangle_list_fn,
13031                         &mangled_name);
13032         if (!NT_STATUS_IS_OK(status)) {
13033                 printf("cli_list of %s returned %s\n",
13034                         star_name,
13035                         nt_errstr(status));
13036                 goto out;
13037         }
13038
13039         if (mangled_name == NULL) {
13040                 goto out;
13041         }
13042
13043         printf("mangled_name = %s\n",
13044                 mangled_name);
13045
13046         /*
13047          * Try a Windows unlink with the mangled name.
13048          * This should *NOT* unlink the 'a' name.
13049          */
13050
13051         windows_unlink_name = talloc_asprintf(cli_posix,
13052                                         "%s\\%s",
13053                                         dname,
13054                                         mangled_name);
13055
13056         status = cli_unlink(cli, windows_unlink_name, 0);
13057         if (!NT_STATUS_IS_OK(status)) {
13058                 printf("cli_unlink of %s returned %s\n",
13059                         windows_unlink_name,
13060                         nt_errstr(status));
13061                 goto out;
13062         }
13063
13064         /* Does 'a' still exist ? */
13065         status = cli_posix_open(cli_posix,
13066                                 aname,
13067                                 O_RDONLY,
13068                                 0,
13069                                 &fnum);
13070         if (!NT_STATUS_IS_OK(status)) {
13071                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13072                         aname,
13073                         nt_errstr(status));
13074                 goto out;
13075         }
13076
13077         status = cli_close(cli_posix, fnum);
13078         if (!NT_STATUS_IS_OK(status)) {
13079                 goto out;
13080         }
13081
13082         correct = true;
13083
13084   out:
13085
13086         TALLOC_FREE(windows_unlink_name);
13087         TALLOC_FREE(mangled_name);
13088
13089         if (cli != NULL) {
13090                 torture_deltree(cli, dname);
13091                 torture_close_connection(cli);
13092         }
13093
13094         if (cli_posix != NULL) {
13095                 torture_close_connection(cli_posix);
13096         }
13097
13098         return correct;
13099 }
13100
13101 static bool run_smb1_wild_mangle_rename_test(int dummy)
13102 {
13103         static struct cli_state *cli_posix = NULL;
13104         static struct cli_state *cli = NULL;
13105         uint16_t fnum = (uint16_t)-1;
13106         bool correct = false;
13107         const char *dname = "smb1_wild_mangle_rename";
13108         const char *fooname = "smb1_wild_mangle_rename/foo";
13109         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13110         const char *wild_name = "smb1_wild_mangle_rename/*";
13111         char *windows_rename_src = NULL;
13112         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13113         char *mangled_name = NULL;
13114         NTSTATUS status;
13115
13116         printf("Starting SMB1 wild mangle rename test\n");
13117
13118         if (!torture_open_connection(&cli_posix, 0)) {
13119                 return false;
13120         }
13121
13122         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13123
13124         status = torture_setup_unix_extensions(cli_posix);
13125         if (!NT_STATUS_IS_OK(status)) {
13126                 printf("server doesn't support POSIX\n");
13127                 return false;
13128         }
13129
13130         /* Open a Windows connection. */
13131         if (!torture_open_connection(&cli, 0)) {
13132                 goto out;
13133         }
13134
13135         smbXcli_conn_set_sockopt(cli->conn, sockops);
13136
13137         /* Ensure we start from fresh. */
13138         torture_deltree(cli, dname);
13139
13140         /*
13141          * Create two files - 'foo' and 'fo*'.
13142          * We need POSIX extensions for this as 'fo*'
13143          * is not a valid Windows name.
13144          */
13145
13146         status = cli_posix_mkdir(cli_posix, dname, 0770);
13147         if (!NT_STATUS_IS_OK(status)) {
13148                 printf("cli_posix_mkdir of %s returned %s\n",
13149                         dname,
13150                         nt_errstr(status));
13151                 goto out;
13152         }
13153
13154         status = cli_posix_open(cli_posix,
13155                                 fooname,
13156                                 O_RDWR|O_CREAT|O_EXCL,
13157                                 0660,
13158                                 &fnum);
13159         if (!NT_STATUS_IS_OK(status)) {
13160                 printf("cli_posix_open (create) of %s returned %s\n",
13161                         fooname,
13162                         nt_errstr(status));
13163                 goto out;
13164         }
13165         status = cli_close(cli_posix, fnum);
13166         if (!NT_STATUS_IS_OK(status)) {
13167                 goto out;
13168         }
13169         status = cli_posix_open(cli_posix,
13170                                 foostar_name,
13171                                 O_RDWR|O_CREAT|O_EXCL,
13172                                 0660,
13173                                 &fnum);
13174         if (!NT_STATUS_IS_OK(status)) {
13175                 printf("cli_posix_open (create) of %s returned %s\n",
13176                         foostar_name,
13177                         nt_errstr(status));
13178                 goto out;
13179         }
13180         status = cli_close(cli_posix, fnum);
13181         if (!NT_STATUS_IS_OK(status)) {
13182                 goto out;
13183         }
13184
13185         /*
13186          * Get the mangled name. We can re-use the
13187          * previous smb1_wild_mangle_list_fn for this.
13188          */
13189
13190         status = cli_list(cli,
13191                         wild_name,
13192                         0,
13193                         smb1_wild_mangle_list_fn,
13194                         &mangled_name);
13195         if (!NT_STATUS_IS_OK(status)) {
13196                 printf("cli_list of %s returned %s\n",
13197                         wild_name,
13198                         nt_errstr(status));
13199                 goto out;
13200         }
13201
13202         if (mangled_name == NULL) {
13203                 goto out;
13204         }
13205
13206         printf("mangled_name = %s\n",
13207                 mangled_name);
13208
13209         /*
13210          * Try a Windows rename with the mangled name.
13211          * This should *NOT* rename the 'foo' name.
13212          */
13213
13214         windows_rename_src = talloc_asprintf(cli_posix,
13215                                         "%s\\%s",
13216                                         dname,
13217                                         mangled_name);
13218
13219         status = cli_rename(cli,
13220                         windows_rename_src,
13221                         windows_rename_dst,
13222                         false);
13223         if (!NT_STATUS_IS_OK(status)) {
13224                 printf("cli_rename of %s -> %s returned %s\n",
13225                         windows_rename_src,
13226                         windows_rename_dst,
13227                         nt_errstr(status));
13228                 goto out;
13229         }
13230
13231         /* Does 'foo' still exist ? */
13232         status = cli_posix_open(cli_posix,
13233                                 fooname,
13234                                 O_RDONLY,
13235                                 0,
13236                                 &fnum);
13237         if (!NT_STATUS_IS_OK(status)) {
13238                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13239                         fooname,
13240                         nt_errstr(status));
13241                 goto out;
13242         }
13243
13244         status = cli_close(cli_posix, fnum);
13245         if (!NT_STATUS_IS_OK(status)) {
13246                 goto out;
13247         }
13248
13249         correct = true;
13250
13251   out:
13252
13253         TALLOC_FREE(mangled_name);
13254         TALLOC_FREE(windows_rename_src);
13255
13256         if (cli != NULL) {
13257                 torture_deltree(cli, dname);
13258                 torture_close_connection(cli);
13259         }
13260
13261         torture_close_connection(cli_posix);
13262
13263         return correct;
13264 }
13265
13266 /*
13267  * Only testing minimal time strings, as the others
13268  * need (locale-dependent) guessing at what strftime does and
13269  * even may differ in builds.
13270  */
13271 static bool timesubst_test(void)
13272 {
13273         TALLOC_CTX *ctx = NULL;
13274         /* Sa 23. Dez 04:33:20 CET 2017 */
13275         const struct timeval tv = { 1514000000, 123 };
13276         const char* expect_minimal = "20171223_033320";
13277         const char* expect_minus   = "20171223_033320_000123";
13278         char *s;
13279         char *env_tz, *orig_tz = NULL;
13280         bool result = true;
13281
13282         ctx = talloc_new(NULL);
13283
13284         env_tz = getenv("TZ");
13285         if(env_tz) {
13286                 orig_tz = talloc_strdup(ctx, env_tz);
13287         }
13288         setenv("TZ", "UTC", 1);
13289
13290         s = minimal_timeval_string(ctx, &tv, false);
13291
13292         if(!s || strcmp(s, expect_minimal)) {
13293                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13294                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13295                 result = false;
13296         }
13297         TALLOC_FREE(s);
13298         s = minimal_timeval_string(ctx, &tv, true);
13299         if(!s || strcmp(s, expect_minus)) {
13300                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13301                        "[%s]\n", s ? s : "<nil>", expect_minus);
13302                 result = false;
13303         }
13304         TALLOC_FREE(s);
13305
13306         if(orig_tz) {
13307                 setenv("TZ", orig_tz, 1);
13308         }
13309
13310         TALLOC_FREE(ctx);
13311         return result;
13312 }
13313
13314 static bool run_local_substitute(int dummy)
13315 {
13316         bool ok = true;
13317
13318         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13319         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13320         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13321         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13322         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13323         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13324         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13325         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13326         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13327         /* Substitution depends on current time, so better test the underlying
13328            formatting function. At least covers %t. */
13329         ok &= timesubst_test();
13330
13331         /* Different captialization rules in sub_basic... */
13332
13333         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13334                        "blaDOM") == 0);
13335
13336         return ok;
13337 }
13338
13339 static bool run_local_base64(int dummy)
13340 {
13341         int i;
13342         bool ret = true;
13343
13344         for (i=1; i<2000; i++) {
13345                 DATA_BLOB blob1, blob2;
13346                 char *b64;
13347
13348                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13349                 blob1.length = i;
13350                 generate_random_buffer(blob1.data, blob1.length);
13351
13352                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13353                 if (b64 == NULL) {
13354                         d_fprintf(stderr, "base64_encode_data_blob failed "
13355                                   "for %d bytes\n", i);
13356                         ret = false;
13357                 }
13358                 blob2 = base64_decode_data_blob(b64);
13359                 TALLOC_FREE(b64);
13360
13361                 if (data_blob_cmp(&blob1, &blob2)) {
13362                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13363                                   "bytes\n", i);
13364                         ret = false;
13365                 }
13366                 TALLOC_FREE(blob1.data);
13367                 data_blob_free(&blob2);
13368         }
13369         return ret;
13370 }
13371
13372 static void parse_fn(const struct gencache_timeout *t,
13373                      DATA_BLOB blob,
13374                      void *private_data)
13375 {
13376         return;
13377 }
13378
13379 static bool run_local_gencache(int dummy)
13380 {
13381         char *val;
13382         time_t tm;
13383         DATA_BLOB blob;
13384         char v;
13385         struct memcache *mem;
13386         int i;
13387
13388         mem = memcache_init(NULL, 0);
13389         if (mem == NULL) {
13390                 d_printf("%s: memcache_init failed\n", __location__);
13391                 return false;
13392         }
13393         memcache_set_global(mem);
13394
13395         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13396                 d_printf("%s: gencache_set() failed\n", __location__);
13397                 return False;
13398         }
13399
13400         if (!gencache_get("foo", NULL, NULL, NULL)) {
13401                 d_printf("%s: gencache_get() failed\n", __location__);
13402                 return False;
13403         }
13404
13405         for (i=0; i<1000000; i++) {
13406                 gencache_parse("foo", parse_fn, NULL);
13407         }
13408
13409         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13410                 d_printf("%s: gencache_get() failed\n", __location__);
13411                 return False;
13412         }
13413         TALLOC_FREE(val);
13414
13415         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13416                 d_printf("%s: gencache_get() failed\n", __location__);
13417                 return False;
13418         }
13419
13420         if (strcmp(val, "bar") != 0) {
13421                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13422                          __location__, val, "bar");
13423                 TALLOC_FREE(val);
13424                 return False;
13425         }
13426
13427         TALLOC_FREE(val);
13428
13429         if (!gencache_del("foo")) {
13430                 d_printf("%s: gencache_del() failed\n", __location__);
13431                 return False;
13432         }
13433         if (gencache_del("foo")) {
13434                 d_printf("%s: second gencache_del() succeeded\n",
13435                          __location__);
13436                 return False;
13437         }
13438
13439         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13440                 d_printf("%s: gencache_get() on deleted entry "
13441                          "succeeded\n", __location__);
13442                 return False;
13443         }
13444
13445         blob = data_blob_string_const_null("bar");
13446         tm = time(NULL) + 60;
13447
13448         if (!gencache_set_data_blob("foo", blob, tm)) {
13449                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13450                 return False;
13451         }
13452
13453         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13454                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13455                 return False;
13456         }
13457
13458         if (strcmp((const char *)blob.data, "bar") != 0) {
13459                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13460                          __location__, (const char *)blob.data, "bar");
13461                 data_blob_free(&blob);
13462                 return False;
13463         }
13464
13465         data_blob_free(&blob);
13466
13467         if (!gencache_del("foo")) {
13468                 d_printf("%s: gencache_del() failed\n", __location__);
13469                 return False;
13470         }
13471         if (gencache_del("foo")) {
13472                 d_printf("%s: second gencache_del() succeeded\n",
13473                          __location__);
13474                 return False;
13475         }
13476
13477         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13478                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13479                          "succeeded\n", __location__);
13480                 return False;
13481         }
13482
13483         v = 1;
13484         blob.data = (uint8_t *)&v;
13485         blob.length = sizeof(v);
13486
13487         if (!gencache_set_data_blob("blob", blob, tm)) {
13488                 d_printf("%s: gencache_set_data_blob() failed\n",
13489                          __location__);
13490                 return false;
13491         }
13492         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13493                 d_printf("%s: gencache_get succeeded\n", __location__);
13494                 return false;
13495         }
13496
13497         return True;
13498 }
13499
13500 static bool rbt_testflags(struct db_context *db, const char *key,
13501                           const char *value)
13502 {
13503         bool ret = false;
13504         NTSTATUS status;
13505         struct db_record *rec;
13506
13507         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13508         if (rec == NULL) {
13509                 d_fprintf(stderr, "fetch_locked failed\n");
13510                 goto done;
13511         }
13512
13513         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13514         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13515                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13516                           nt_errstr(status));
13517                 goto done;
13518         }
13519
13520         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13521                                      TDB_INSERT);
13522         if (!NT_STATUS_IS_OK(status)) {
13523                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13524                           nt_errstr(status));
13525                 goto done;
13526         }
13527
13528         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13529         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13530                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13531                           nt_errstr(status));
13532                 goto done;
13533         }
13534
13535         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13536         if (!NT_STATUS_IS_OK(status)) {
13537                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13538                           nt_errstr(status));
13539                 goto done;
13540         }
13541
13542         ret = true;
13543 done:
13544         TALLOC_FREE(rec);
13545         return ret;
13546 }
13547
13548 static bool rbt_testval(struct db_context *db, const char *key,
13549                         const char *value)
13550 {
13551         struct db_record *rec;
13552         TDB_DATA data = string_tdb_data(value);
13553         bool ret = false;
13554         NTSTATUS status;
13555         TDB_DATA dbvalue;
13556
13557         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13558         if (rec == NULL) {
13559                 d_fprintf(stderr, "fetch_locked failed\n");
13560                 goto done;
13561         }
13562         status = dbwrap_record_store(rec, data, 0);
13563         if (!NT_STATUS_IS_OK(status)) {
13564                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13565                 goto done;
13566         }
13567         TALLOC_FREE(rec);
13568
13569         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13570         if (rec == NULL) {
13571                 d_fprintf(stderr, "second fetch_locked failed\n");
13572                 goto done;
13573         }
13574
13575         dbvalue = dbwrap_record_get_value(rec);
13576         if ((dbvalue.dsize != data.dsize)
13577             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13578                 d_fprintf(stderr, "Got wrong data back\n");
13579                 goto done;
13580         }
13581
13582         ret = true;
13583  done:
13584         TALLOC_FREE(rec);
13585         return ret;
13586 }
13587
13588 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13589 {
13590         int *count2 = (int *)private_data;
13591         (*count2)++;
13592         return 0;
13593 }
13594
13595 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13596 {
13597         int *count2 = (int *)private_data;
13598         (*count2)++;
13599         dbwrap_record_delete(rec);
13600         return 0;
13601 }
13602
13603 static bool run_local_rbtree(int dummy)
13604 {
13605         struct db_context *db;
13606         bool ret = false;
13607         int i;
13608         NTSTATUS status;
13609         int count = 0;
13610         int count2 = 0;
13611
13612         db = db_open_rbt(NULL);
13613
13614         if (db == NULL) {
13615                 d_fprintf(stderr, "db_open_rbt failed\n");
13616                 return false;
13617         }
13618
13619         if (!rbt_testflags(db, "firstkey", "firstval")) {
13620                 goto done;
13621         }
13622
13623         for (i = 0; i < 999; i++) {
13624                 char key[sizeof("key-9223372036854775807")];
13625                 char value[sizeof("value-9223372036854775807")];
13626
13627                 snprintf(key, sizeof(key), "key%ld", random());
13628                 snprintf(value, sizeof(value) ,"value%ld", random());
13629
13630                 if (!rbt_testval(db, key, value)) {
13631                         goto done;
13632                 }
13633
13634                 snprintf(value, sizeof(value) ,"value%ld", random());
13635
13636                 if (!rbt_testval(db, key, value)) {
13637                         goto done;
13638                 }
13639         }
13640
13641         ret = true;
13642         count = 0; count2 = 0;
13643         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13644                                       &count2, &count);
13645         printf("%s: read1: %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(db, local_rbtree_traverse_delete,
13651                                  &count2, &count);
13652         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13653         if ((count != count2) || (count != 1000)) {
13654                 ret = false;
13655         }
13656         count = 0; count2 = 0;
13657         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13658                                       &count2, &count);
13659         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13660         if ((count != count2) || (count != 0)) {
13661                 ret = false;
13662         }
13663
13664  done:
13665         TALLOC_FREE(db);
13666         return ret;
13667 }
13668
13669
13670 /*
13671   local test for character set functions
13672
13673   This is a very simple test for the functionality in convert_string_error()
13674  */
13675 static bool run_local_convert_string(int dummy)
13676 {
13677         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13678         const char *test_strings[2] = { "March", "M\303\244rz" };
13679         char dst[7];
13680         int i;
13681
13682         for (i=0; i<2; i++) {
13683                 const char *str = test_strings[i];
13684                 int len = strlen(str);
13685                 size_t converted_size;
13686                 bool ret;
13687
13688                 memset(dst, 'X', sizeof(dst));
13689
13690                 /* first try with real source length */
13691                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13692                                            str, len,
13693                                            dst, sizeof(dst),
13694                                            &converted_size);
13695                 if (ret != true) {
13696                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13697                         goto failed;
13698                 }
13699
13700                 if (converted_size != len) {
13701                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13702                                   str, len, (int)converted_size);
13703                         goto failed;
13704                 }
13705
13706                 if (strncmp(str, dst, converted_size) != 0) {
13707                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13708                         goto failed;
13709                 }
13710
13711                 if (strlen(str) != converted_size) {
13712                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13713                                   (int)strlen(str), (int)converted_size);
13714                         goto failed;
13715                 }
13716
13717                 if (dst[converted_size] != 'X') {
13718                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13719                         goto failed;
13720                 }
13721
13722                 /* now with srclen==-1, this causes the nul to be
13723                  * converted too */
13724                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13725                                            str, -1,
13726                                            dst, sizeof(dst),
13727                                            &converted_size);
13728                 if (ret != true) {
13729                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13730                         goto failed;
13731                 }
13732
13733                 if (converted_size != len+1) {
13734                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13735                                   str, len, (int)converted_size);
13736                         goto failed;
13737                 }
13738
13739                 if (strncmp(str, dst, converted_size) != 0) {
13740                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13741                         goto failed;
13742                 }
13743
13744                 if (len+1 != converted_size) {
13745                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13746                                   len+1, (int)converted_size);
13747                         goto failed;
13748                 }
13749
13750                 if (dst[converted_size] != 'X') {
13751                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13752                         goto failed;
13753                 }
13754
13755         }
13756
13757
13758         TALLOC_FREE(tmp_ctx);
13759         return true;
13760 failed:
13761         TALLOC_FREE(tmp_ctx);
13762         return false;
13763 }
13764
13765 static bool run_local_string_to_sid(int dummy) {
13766         struct dom_sid sid;
13767
13768         if (string_to_sid(&sid, "S--1-5-32-545")) {
13769                 printf("allowing S--1-5-32-545\n");
13770                 return false;
13771         }
13772         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13773                 printf("allowing S-1-5-32-+545\n");
13774                 return false;
13775         }
13776         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")) {
13777                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13778                 return false;
13779         }
13780         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13781                 printf("allowing S-1-5-32-545-abc\n");
13782                 return false;
13783         }
13784         if (string_to_sid(&sid, "S-300-5-32-545")) {
13785                 printf("allowing S-300-5-32-545\n");
13786                 return false;
13787         }
13788         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13789                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13790                 return false;
13791         }
13792         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13793                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13794                 return false;
13795         }
13796         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13797                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13798                 return false;
13799         }
13800         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13801                 printf("could not parse S-1-5-32-545\n");
13802                 return false;
13803         }
13804         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13805                 struct dom_sid_buf buf;
13806                 printf("mis-parsed S-1-5-32-545 as %s\n",
13807                        dom_sid_str_buf(&sid, &buf));
13808                 return false;
13809         }
13810         return true;
13811 }
13812
13813 static bool sid_to_string_test(const char *expected) {
13814         char *str;
13815         bool res = true;
13816         struct dom_sid sid;
13817
13818         if (!string_to_sid(&sid, expected)) {
13819                 printf("could not parse %s\n", expected);
13820                 return false;
13821         }
13822
13823         str = dom_sid_string(NULL, &sid);
13824         if (strcmp(str, expected)) {
13825                 printf("Comparison failed (%s != %s)\n", str, expected);
13826                 res = false;
13827         }
13828         TALLOC_FREE(str);
13829         return res;
13830 }
13831
13832 static bool run_local_sid_to_string(int dummy) {
13833         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13834                 return false;
13835         if (!sid_to_string_test("S-1-545"))
13836                 return false;
13837         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13838                 return false;
13839         return true;
13840 }
13841
13842 static bool run_local_binary_to_sid(int dummy) {
13843         ssize_t ret;
13844         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13845         static const uint8_t good_binary_sid[] = {
13846                 0x1, /* revision number */
13847                 15, /* num auths */
13848                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13849                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13850                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13851                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13852                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13853                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13854                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13855                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13856                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13857                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13858                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13859                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13860                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13861                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13862                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13863                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13864         };
13865
13866         static const uint8_t long_binary_sid[] = {
13867                 0x1, /* revision number */
13868                 15, /* num auths */
13869                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13870                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13871                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13872                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13873                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13874                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13875                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13876                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13877                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13878                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13879                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13880                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13881                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13882                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13883                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13884                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13885                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13886                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13887                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13888         };
13889
13890         static const uint8_t long_binary_sid2[] = {
13891                 0x1, /* revision number */
13892                 32, /* num auths */
13893                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13894                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13895                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13896                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13897                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13898                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13899                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13900                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13901                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13902                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13903                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13904                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13905                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13906                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13907                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13908                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13909                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13910                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13911                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13912                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13913                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13914                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13915                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13916                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13917                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13918                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13919                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13920                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13921                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13922                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13923                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13924                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13925                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13926         };
13927
13928         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13929         if (ret == -1) {
13930                 return false;
13931         }
13932         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13933         if (ret != -1) {
13934                 return false;
13935         }
13936         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13937         if (ret != -1) {
13938                 return false;
13939         }
13940         return true;
13941 }
13942
13943 /* Split a path name into filename and stream name components. Canonicalise
13944  * such that an implicit $DATA token is always explicit.
13945  *
13946  * The "specification" of this function can be found in the
13947  * run_local_stream_name() function in torture.c, I've tried those
13948  * combinations against a W2k3 server.
13949  */
13950
13951 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13952                                        char **pbase, char **pstream)
13953 {
13954         char *base = NULL;
13955         char *stream = NULL;
13956         char *sname; /* stream name */
13957         const char *stype; /* stream type */
13958
13959         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13960
13961         sname = strchr_m(fname, ':');
13962
13963         if (sname == NULL) {
13964                 if (pbase != NULL) {
13965                         base = talloc_strdup(mem_ctx, fname);
13966                         NT_STATUS_HAVE_NO_MEMORY(base);
13967                 }
13968                 goto done;
13969         }
13970
13971         if (pbase != NULL) {
13972                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13973                 NT_STATUS_HAVE_NO_MEMORY(base);
13974         }
13975
13976         sname += 1;
13977
13978         stype = strchr_m(sname, ':');
13979
13980         if (stype == NULL) {
13981                 sname = talloc_strdup(mem_ctx, sname);
13982                 stype = "$DATA";
13983         }
13984         else {
13985                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13986                         /*
13987                          * If there is an explicit stream type, so far we only
13988                          * allow $DATA. Is there anything else allowed? -- vl
13989                          */
13990                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13991                         TALLOC_FREE(base);
13992                         return NT_STATUS_OBJECT_NAME_INVALID;
13993                 }
13994                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13995                 stype += 1;
13996         }
13997
13998         if (sname == NULL) {
13999                 TALLOC_FREE(base);
14000                 return NT_STATUS_NO_MEMORY;
14001         }
14002
14003         if (sname[0] == '\0') {
14004                 /*
14005                  * no stream name, so no stream
14006                  */
14007                 goto done;
14008         }
14009
14010         if (pstream != NULL) {
14011                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14012                 if (stream == NULL) {
14013                         TALLOC_FREE(sname);
14014                         TALLOC_FREE(base);
14015                         return NT_STATUS_NO_MEMORY;
14016                 }
14017                 /*
14018                  * upper-case the type field
14019                  */
14020                 (void)strupper_m(strchr_m(stream, ':')+1);
14021         }
14022
14023  done:
14024         if (pbase != NULL) {
14025                 *pbase = base;
14026         }
14027         if (pstream != NULL) {
14028                 *pstream = stream;
14029         }
14030         return NT_STATUS_OK;
14031 }
14032
14033 static bool test_stream_name(const char *fname, const char *expected_base,
14034                              const char *expected_stream,
14035                              NTSTATUS expected_status)
14036 {
14037         NTSTATUS status;
14038         char *base = NULL;
14039         char *stream = NULL;
14040
14041         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14042         if (!NT_STATUS_EQUAL(status, expected_status)) {
14043                 goto error;
14044         }
14045
14046         if (!NT_STATUS_IS_OK(status)) {
14047                 return true;
14048         }
14049
14050         if (base == NULL) goto error;
14051
14052         if (strcmp(expected_base, base) != 0) goto error;
14053
14054         if ((expected_stream != NULL) && (stream == NULL)) goto error;
14055         if ((expected_stream == NULL) && (stream != NULL)) goto error;
14056
14057         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14058                 goto error;
14059
14060         TALLOC_FREE(base);
14061         TALLOC_FREE(stream);
14062         return true;
14063
14064  error:
14065         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14066                   fname, expected_base ? expected_base : "<NULL>",
14067                   expected_stream ? expected_stream : "<NULL>",
14068                   nt_errstr(expected_status));
14069         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14070                   base ? base : "<NULL>", stream ? stream : "<NULL>",
14071                   nt_errstr(status));
14072         TALLOC_FREE(base);
14073         TALLOC_FREE(stream);
14074         return false;
14075 }
14076
14077 static bool run_local_stream_name(int dummy)
14078 {
14079         bool ret = true;
14080
14081         ret &= test_stream_name(
14082                 "bla", "bla", NULL, NT_STATUS_OK);
14083         ret &= test_stream_name(
14084                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14085         ret &= test_stream_name(
14086                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14087         ret &= test_stream_name(
14088                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14089         ret &= test_stream_name(
14090                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14091         ret &= test_stream_name(
14092                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14093         ret &= test_stream_name(
14094                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14095         ret &= test_stream_name(
14096                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14097
14098         return ret;
14099 }
14100
14101 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14102 {
14103         if (a.length != b.length) {
14104                 printf("a.length=%d != b.length=%d\n",
14105                        (int)a.length, (int)b.length);
14106                 return false;
14107         }
14108         if (memcmp(a.data, b.data, a.length) != 0) {
14109                 printf("a.data and b.data differ\n");
14110                 return false;
14111         }
14112         return true;
14113 }
14114
14115 static bool run_local_memcache(int dummy)
14116 {
14117         struct memcache *cache;
14118         DATA_BLOB k1, k2, k3, k4, k5;
14119         DATA_BLOB d1, d3;
14120         DATA_BLOB v1, v3;
14121
14122         TALLOC_CTX *mem_ctx;
14123         char *ptr1 = NULL;
14124         char *ptr2 = NULL;
14125         char *ptr3 = NULL;
14126
14127         char *str1, *str2;
14128         size_t size1, size2;
14129         bool ret = false;
14130
14131         mem_ctx = talloc_init("foo");
14132         if (mem_ctx == NULL) {
14133                 return false;
14134         }
14135
14136         /* STAT_CACHE TESTS */
14137
14138         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14139
14140         if (cache == NULL) {
14141                 printf("memcache_init failed\n");
14142                 return false;
14143         }
14144
14145         d1 = data_blob_const("d1", 2);
14146         d3 = data_blob_const("d3", 2);
14147
14148         k1 = data_blob_const("d1", 2);
14149         k2 = data_blob_const("d2", 2);
14150         k3 = data_blob_const("d3", 2);
14151         k4 = data_blob_const("d4", 2);
14152         k5 = data_blob_const("d5", 2);
14153
14154         memcache_add(cache, STAT_CACHE, k1, d1);
14155
14156         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14157                 printf("could not find k1\n");
14158                 return false;
14159         }
14160         if (!data_blob_equal(d1, v1)) {
14161                 return false;
14162         }
14163
14164         memcache_add(cache, STAT_CACHE, k1, d3);
14165
14166         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14167                 printf("could not find replaced k1\n");
14168                 return false;
14169         }
14170         if (!data_blob_equal(d3, v3)) {
14171                 return false;
14172         }
14173
14174         TALLOC_FREE(cache);
14175
14176         /* GETWD_CACHE TESTS */
14177         str1 = talloc_strdup(mem_ctx, "string1");
14178         if (str1 == NULL) {
14179                 return false;
14180         }
14181         ptr2 = str1; /* Keep an alias for comparison. */
14182
14183         str2 = talloc_strdup(mem_ctx, "string2");
14184         if (str2 == NULL) {
14185                 return false;
14186         }
14187
14188         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14189         if (cache == NULL) {
14190                 printf("memcache_init failed\n");
14191                 return false;
14192         }
14193
14194         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14195         /* str1 == NULL now. */
14196         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14197         if (ptr1 == NULL) {
14198                 printf("could not find k2\n");
14199                 return false;
14200         }
14201         if (ptr1 != ptr2) {
14202                 printf("fetch of k2 got wrong string\n");
14203                 return false;
14204         }
14205
14206         /* Add a blob to ensure k2 gets purged. */
14207         d3 = data_blob_talloc_zero(mem_ctx, 180);
14208         memcache_add(cache, STAT_CACHE, k3, d3);
14209
14210         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14211         if (ptr2 != NULL) {
14212                 printf("Did find k2, should have been purged\n");
14213                 return false;
14214         }
14215
14216         /*
14217          * Test that talloc size also is accounted in memcache and
14218          * causes purge of other object.
14219          */
14220
14221         str1 = talloc_zero_size(mem_ctx, 100);
14222         str2 = talloc_zero_size(mem_ctx, 100);
14223
14224         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14225         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14226
14227         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14228         if (ptr3 != NULL) {
14229                 printf("Did find k4, should have been purged\n");
14230                 return false;
14231         }
14232
14233         /*
14234          * Test that adding a duplicate non-talloced
14235          * key/value on top of a talloced key/value takes account
14236          * of the talloc_freed value size.
14237          */
14238         TALLOC_FREE(cache);
14239         TALLOC_FREE(mem_ctx);
14240
14241         mem_ctx = talloc_init("key_replace");
14242         if (mem_ctx == NULL) {
14243                 return false;
14244         }
14245
14246         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14247         if (cache == NULL) {
14248                 return false;
14249         }
14250
14251         /*
14252          * Add a 100 byte talloced string. This will
14253          * store a (4 or 8 byte) pointer and record the
14254          * total talloced size.
14255          */
14256         str1 = talloc_zero_size(mem_ctx, 100);
14257         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14258         /*
14259          * Now overwrite with a small talloced
14260          * value. This should fit in the existing size
14261          * and the total talloced size should be removed
14262          * from the cache size.
14263          */
14264         str1 = talloc_zero_size(mem_ctx, 2);
14265         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14266         /*
14267          * Now store a 20 byte string. If the
14268          * total talloced size wasn't accounted for
14269          * and removed in the overwrite, then this
14270          * will evict k4.
14271          */
14272         str2 = talloc_zero_size(mem_ctx, 20);
14273         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14274
14275         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14276         if (ptr3 == NULL) {
14277                 printf("Did not find k4, should not have been purged\n");
14278                 return false;
14279         }
14280
14281         TALLOC_FREE(cache);
14282         TALLOC_FREE(mem_ctx);
14283
14284         mem_ctx = talloc_init("foo");
14285         if (mem_ctx == NULL) {
14286                 return false;
14287         }
14288
14289         cache = memcache_init(NULL, 0);
14290         if (cache == NULL) {
14291                 return false;
14292         }
14293
14294         str1 = talloc_strdup(mem_ctx, "string1");
14295         if (str1 == NULL) {
14296                 return false;
14297         }
14298         str2 = talloc_strdup(mem_ctx, "string2");
14299         if (str2 == NULL) {
14300                 return false;
14301         }
14302         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14303                             data_blob_string_const("torture"), &str1);
14304         size1 = talloc_total_size(cache);
14305
14306         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14307                             data_blob_string_const("torture"), &str2);
14308         size2 = talloc_total_size(cache);
14309
14310         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14311
14312         if (size2 > size1) {
14313                 printf("memcache leaks memory!\n");
14314                 goto fail;
14315         }
14316
14317         ret = true;
14318  fail:
14319         TALLOC_FREE(cache);
14320         return ret;
14321 }
14322
14323 static void wbclient_done(struct tevent_req *req)
14324 {
14325         wbcErr wbc_err;
14326         struct winbindd_response *wb_resp;
14327         int *i = (int *)tevent_req_callback_data_void(req);
14328
14329         wbc_err = wb_trans_recv(req, req, &wb_resp);
14330         TALLOC_FREE(req);
14331         *i += 1;
14332         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14333 }
14334
14335 static bool run_wbclient_multi_ping(int dummy)
14336 {
14337         struct tevent_context *ev;
14338         struct wb_context **wb_ctx;
14339         struct winbindd_request wb_req;
14340         bool result = false;
14341         int i, j;
14342
14343         BlockSignals(True, SIGPIPE);
14344
14345         ev = tevent_context_init(talloc_tos());
14346         if (ev == NULL) {
14347                 goto fail;
14348         }
14349
14350         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14351         if (wb_ctx == NULL) {
14352                 goto fail;
14353         }
14354
14355         ZERO_STRUCT(wb_req);
14356         wb_req.cmd = WINBINDD_PING;
14357
14358         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14359
14360         for (i=0; i<torture_nprocs; i++) {
14361                 wb_ctx[i] = wb_context_init(ev, NULL);
14362                 if (wb_ctx[i] == NULL) {
14363                         goto fail;
14364                 }
14365                 for (j=0; j<torture_numops; j++) {
14366                         struct tevent_req *req;
14367                         req = wb_trans_send(ev, ev, wb_ctx[i],
14368                                             (j % 2) == 0, &wb_req);
14369                         if (req == NULL) {
14370                                 goto fail;
14371                         }
14372                         tevent_req_set_callback(req, wbclient_done, &i);
14373                 }
14374         }
14375
14376         i = 0;
14377
14378         while (i < torture_nprocs * torture_numops) {
14379                 tevent_loop_once(ev);
14380         }
14381
14382         result = true;
14383  fail:
14384         TALLOC_FREE(ev);
14385         return result;
14386 }
14387
14388 static bool dbtrans_inc(struct db_context *db)
14389 {
14390         struct db_record *rec;
14391         uint32_t val;
14392         bool ret = false;
14393         NTSTATUS status;
14394         TDB_DATA value;
14395
14396         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14397         if (rec == NULL) {
14398                 printf(__location__ "fetch_lock failed\n");
14399                 return false;
14400         }
14401
14402         value = dbwrap_record_get_value(rec);
14403
14404         if (value.dsize != sizeof(uint32_t)) {
14405                 printf(__location__ "value.dsize = %d\n",
14406                        (int)value.dsize);
14407                 goto fail;
14408         }
14409
14410         memcpy(&val, value.dptr, sizeof(val));
14411         val += 1;
14412
14413         status = dbwrap_record_store(
14414                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14415         if (!NT_STATUS_IS_OK(status)) {
14416                 printf(__location__ "store failed: %s\n",
14417                        nt_errstr(status));
14418                 goto fail;
14419         }
14420
14421         ret = true;
14422 fail:
14423         TALLOC_FREE(rec);
14424         return ret;
14425 }
14426
14427 static bool run_local_dbtrans(int dummy)
14428 {
14429         struct db_context *db;
14430         struct db_record *rec;
14431         NTSTATUS status;
14432         uint32_t initial;
14433         int res;
14434         TDB_DATA value;
14435
14436         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14437                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14438                      DBWRAP_FLAG_NONE);
14439         if (db == NULL) {
14440                 printf("Could not open transtest.db\n");
14441                 return false;
14442         }
14443
14444         res = dbwrap_transaction_start(db);
14445         if (res != 0) {
14446                 printf(__location__ "transaction_start failed\n");
14447                 return false;
14448         }
14449
14450         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14451         if (rec == NULL) {
14452                 printf(__location__ "fetch_lock failed\n");
14453                 return false;
14454         }
14455
14456         value = dbwrap_record_get_value(rec);
14457
14458         if (value.dptr == NULL) {
14459                 initial = 0;
14460                 status = dbwrap_record_store(
14461                         rec, make_tdb_data((uint8_t *)&initial,
14462                                            sizeof(initial)),
14463                         0);
14464                 if (!NT_STATUS_IS_OK(status)) {
14465                         printf(__location__ "store returned %s\n",
14466                                nt_errstr(status));
14467                         return false;
14468                 }
14469         }
14470
14471         TALLOC_FREE(rec);
14472
14473         res = dbwrap_transaction_commit(db);
14474         if (res != 0) {
14475                 printf(__location__ "transaction_commit failed\n");
14476                 return false;
14477         }
14478
14479         while (true) {
14480                 uint32_t val, val2;
14481                 int i;
14482
14483                 res = dbwrap_transaction_start(db);
14484                 if (res != 0) {
14485                         printf(__location__ "transaction_start failed\n");
14486                         break;
14487                 }
14488
14489                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14490                 if (!NT_STATUS_IS_OK(status)) {
14491                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14492                                nt_errstr(status));
14493                         break;
14494                 }
14495
14496                 for (i=0; i<10; i++) {
14497                         if (!dbtrans_inc(db)) {
14498                                 return false;
14499                         }
14500                 }
14501
14502                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14503                 if (!NT_STATUS_IS_OK(status)) {
14504                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14505                                nt_errstr(status));
14506                         break;
14507                 }
14508
14509                 if (val2 != val + 10) {
14510                         printf(__location__ "val=%d, val2=%d\n",
14511                                (int)val, (int)val2);
14512                         break;
14513                 }
14514
14515                 printf("val2=%d\r", val2);
14516
14517                 res = dbwrap_transaction_commit(db);
14518                 if (res != 0) {
14519                         printf(__location__ "transaction_commit failed\n");
14520                         break;
14521                 }
14522         }
14523
14524         TALLOC_FREE(db);
14525         return true;
14526 }
14527
14528 /*
14529  * Just a dummy test to be run under a debugger. There's no real way
14530  * to inspect the tevent_poll specific function from outside of
14531  * tevent_poll.c.
14532  */
14533
14534 static bool run_local_tevent_poll(int dummy)
14535 {
14536         struct tevent_context *ev;
14537         struct tevent_fd *fd1, *fd2;
14538         bool result = false;
14539
14540         ev = tevent_context_init_byname(NULL, "poll");
14541         if (ev == NULL) {
14542                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14543                 goto fail;
14544         }
14545
14546         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14547         if (fd1 == NULL) {
14548                 d_fprintf(stderr, "tevent_add_fd failed\n");
14549                 goto fail;
14550         }
14551         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14552         if (fd2 == NULL) {
14553                 d_fprintf(stderr, "tevent_add_fd failed\n");
14554                 goto fail;
14555         }
14556         TALLOC_FREE(fd2);
14557
14558         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14559         if (fd2 == NULL) {
14560                 d_fprintf(stderr, "tevent_add_fd failed\n");
14561                 goto fail;
14562         }
14563
14564         result = true;
14565 fail:
14566         TALLOC_FREE(ev);
14567         return result;
14568 }
14569
14570 static bool run_local_hex_encode_buf(int dummy)
14571 {
14572         char buf[17];
14573         uint8_t src[8];
14574         size_t i;
14575
14576         for (i=0; i<sizeof(src); i++) {
14577                 src[i] = i;
14578         }
14579         hex_encode_buf(buf, src, sizeof(src));
14580         if (strcmp(buf, "0001020304050607") != 0) {
14581                 return false;
14582         }
14583         hex_encode_buf(buf, NULL, 0);
14584         if (buf[0] != '\0') {
14585                 return false;
14586         }
14587         return true;
14588 }
14589
14590 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14591         "0.0.0.0",
14592         "::0",
14593         "1.2.3.1",
14594         "0.0.0.0",
14595         "0.0.0.0",
14596         "1.2.3.2",
14597         "1.2.3.3",
14598         "1.2.3.4",
14599         "1.2.3.5",
14600         "::0",
14601         "1.2.3.6",
14602         "1.2.3.7",
14603         "::0",
14604         "::0",
14605         "::0",
14606         "1.2.3.8",
14607         "1.2.3.9",
14608         "1.2.3.10",
14609         "1.2.3.11",
14610         "1.2.3.12",
14611         "1.2.3.13",
14612         "1001:1111:1111:1000:0:1111:1111:1111",
14613         "1.2.3.1",
14614         "1.2.3.2",
14615         "1.2.3.3",
14616         "1.2.3.12",
14617         "::0",
14618         "::0"
14619 };
14620
14621 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14622         "1.2.3.1",
14623         "1.2.3.2",
14624         "1.2.3.3",
14625         "1.2.3.4",
14626         "1.2.3.5",
14627         "1.2.3.6",
14628         "1.2.3.7",
14629         "1.2.3.8",
14630         "1.2.3.9",
14631         "1.2.3.10",
14632         "1.2.3.11",
14633         "1.2.3.12",
14634         "1.2.3.13",
14635         "1001:1111:1111:1000:0:1111:1111:1111"
14636 };
14637
14638 static bool run_local_remove_duplicate_addrs2(int dummy)
14639 {
14640         struct samba_sockaddr test_vector[28];
14641         size_t count, i;
14642
14643         /* Construct the sockaddr_storage test vector. */
14644         for (i = 0; i < 28; i++) {
14645                 struct addrinfo hints;
14646                 struct addrinfo *res = NULL;
14647                 int ret;
14648
14649                 memset(&hints, '\0', sizeof(hints));
14650                 hints.ai_flags = AI_NUMERICHOST;
14651                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14652                                 NULL,
14653                                 &hints,
14654                                 &res);
14655                 if (ret) {
14656                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14657                                 remove_duplicate_addrs2_test_strings_vector[i]);
14658                         return false;
14659                 }
14660                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14661                 memcpy(&test_vector[i].u.ss,
14662                         res->ai_addr,
14663                         res->ai_addrlen);
14664                 freeaddrinfo(res);
14665         }
14666
14667         count = remove_duplicate_addrs2(test_vector, i);
14668
14669         if (count != 14) {
14670                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14671                         count);
14672                 return false;
14673         }
14674
14675         for (i = 0; i < count; i++) {
14676                 char addr[INET6_ADDRSTRLEN];
14677
14678                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14679
14680                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14681                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14682                                 i,
14683                                 addr,
14684                                 remove_duplicate_addrs2_test_strings_result[i]);
14685                         return false;
14686                 }
14687         }
14688
14689         printf("run_local_remove_duplicate_addrs2: success\n");
14690         return true;
14691 }
14692
14693 static bool run_local_tdb_opener(int dummy)
14694 {
14695         TDB_CONTEXT *t;
14696         unsigned v = 0;
14697
14698         while (1) {
14699                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14700                              O_RDWR|O_CREAT, 0755);
14701                 if (t == NULL) {
14702                         perror("tdb_open failed");
14703                         return false;
14704                 }
14705                 tdb_close(t);
14706
14707                 v += 1;
14708                 printf("\r%u", v);
14709         }
14710         return true;
14711 }
14712
14713 static bool run_local_tdb_writer(int dummy)
14714 {
14715         TDB_CONTEXT *t;
14716         unsigned v = 0;
14717         TDB_DATA val;
14718
14719         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14720         if (t == 0) {
14721                 perror("tdb_open failed");
14722                 return 1;
14723         }
14724
14725         val.dptr = (uint8_t *)&v;
14726         val.dsize = sizeof(v);
14727
14728         while (1) {
14729                 TDB_DATA data;
14730                 int ret;
14731
14732                 ret = tdb_store(t, val, val, 0);
14733                 if (ret != 0) {
14734                         printf("%s\n", tdb_errorstr(t));
14735                 }
14736                 v += 1;
14737                 printf("\r%u", v);
14738
14739                 data = tdb_fetch(t, val);
14740                 if (data.dptr != NULL) {
14741                         SAFE_FREE(data.dptr);
14742                 }
14743         }
14744         return true;
14745 }
14746
14747 static bool run_local_canonicalize_path(int dummy)
14748 {
14749         const char *src[] = {
14750                         "/foo/..",
14751                         "/..",
14752                         "/foo/bar/../baz",
14753                         "/foo/././",
14754                         "/../foo",
14755                         ".././././",
14756                         ".././././../../../boo",
14757                         "./..",
14758                         "/",
14759                         "/../../",
14760                         "/foo/../",
14761                         "/./././",
14762                         "/./././.",
14763                         "/.../././.",
14764                         "/./././.foo",
14765                         "/./././.foo.",
14766                         "/./././foo.",
14767                         "/foo/bar/..",
14768                         "/foo/bar/../baz/",
14769                         "////////////////",
14770                         "/////////./././././.",
14771                         "/./.././../.boo/../baz",
14772                         "/a/component/path",
14773                         "/a/component/path/",
14774                         "/a/component/path/..",
14775                         "/a/component/../path/",
14776                         "///a/./././///component/../////path/",
14777                         NULL
14778                         };
14779         const char *dst[] = {
14780                         "/",
14781                         "/",
14782                         "/foo/baz",
14783                         "/foo",
14784                         "/foo",
14785                         "/",
14786                         "/boo",
14787                         "/",
14788                         "/",
14789                         "/",
14790                         "/",
14791                         "/",
14792                         "/",
14793                         "/...",
14794                         "/.foo",
14795                         "/.foo.",
14796                         "/foo.",
14797                         "/foo",
14798                         "/foo/baz",
14799                         "/",
14800                         "/",
14801                         "/baz",
14802                         "/a/component/path",
14803                         "/a/component/path",
14804                         "/a/component",
14805                         "/a/path",
14806                         "/a/path",
14807                         NULL
14808                         };
14809         unsigned int i;
14810
14811         for (i = 0; src[i] != NULL; i++) {
14812                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14813                 if (d == NULL) {
14814                         perror("talloc fail\n");
14815                         return false;
14816                 }
14817                 if (strcmp(d, dst[i]) != 0) {
14818                         d_fprintf(stderr,
14819                                 "canonicalize mismatch %s -> %s != %s",
14820                                 src[i], d, dst[i]);
14821                         return false;
14822                 }
14823                 talloc_free(d);
14824         }
14825         return true;
14826 }
14827 struct session_setup_nt1_truncated_state {
14828         uint16_t vwv[13];
14829         uint8_t bytes[20];
14830 };
14831
14832 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14833
14834 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14835                 TALLOC_CTX *mem_ctx,
14836                 struct tevent_context *ev,
14837                 struct smbXcli_conn *conn)
14838 {
14839         uint16_t *vwv = NULL;
14840         uint8_t *bytes = NULL;
14841         const char *pass = "12345678";
14842         const char *uname = "z";
14843         struct session_setup_nt1_truncated_state *state = NULL;
14844         struct tevent_req *req = NULL;
14845         struct tevent_req *subreq = NULL;
14846
14847         req = tevent_req_create(mem_ctx,
14848                                 &state,
14849                                 struct session_setup_nt1_truncated_state);
14850         if (req == NULL) {
14851                 return NULL;
14852         }
14853         vwv = &state->vwv[0];
14854         bytes = &state->bytes[0];
14855
14856         SCVAL(vwv+0,  0, 0xff);
14857         SCVAL(vwv+0,  1, 0);
14858         SSVAL(vwv+1,  0, 0);
14859         SSVAL(vwv+2,  0, 8192);
14860         SSVAL(vwv+3,  0, 2);
14861         SSVAL(vwv+4,  0, 1);
14862         SIVAL(vwv+5,  0, 0);
14863         SSVAL(vwv+7,  0, strlen(pass)); /* OEMPasswordLen */
14864         SSVAL(vwv+8,  0, 0); /* UnicodePasswordLen */
14865         SSVAL(vwv+9,  0, 0); /* reserved */
14866         SSVAL(vwv+10, 0, 0); /* reserved */
14867         SIVAL(vwv+11, 0, CAP_STATUS32);
14868
14869         memcpy(bytes, pass, strlen(pass));
14870         bytes += strlen(pass);
14871         memcpy(bytes, uname, strlen(uname)+1);
14872
14873         subreq = smb1cli_req_send(state, ev, conn,
14874                                   SMBsesssetupX,
14875                                   0, /*  additional_flags */
14876                                   0, /*  clear_flags */
14877                                   0, /*  additional_flags2 */
14878                                   0, /*  clear_flags2 */
14879                                   10000, /* timeout_msec */
14880                                   getpid(),
14881                                   NULL, /* tcon */
14882                                   NULL, /* session */
14883                                   13, /* wct */
14884                                   state->vwv,
14885                                   strlen(pass), /* Truncate length at password. */
14886                                   state->bytes);
14887         if (tevent_req_nomem(subreq, req)) {
14888                 return tevent_req_post(req, ev);
14889         }
14890         tevent_req_set_callback(subreq,
14891                                 smb1_session_setup_nt1_truncated_done,
14892                                 req);
14893         return req;
14894 }
14895
14896 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14897 {
14898         struct tevent_req *req =
14899                 tevent_req_callback_data(subreq,
14900                 struct tevent_req);
14901         struct session_setup_nt1_truncated_state *state =
14902                 tevent_req_data(req,
14903                 struct session_setup_nt1_truncated_state);
14904         NTSTATUS status;
14905         struct smb1cli_req_expected_response expected[] = {
14906         {
14907                 .status = NT_STATUS_OK,
14908                 .wct    = 3,
14909         },
14910         };
14911
14912         status = smb1cli_req_recv(subreq, state,
14913                                   NULL,
14914                                   NULL,
14915                                   NULL,
14916                                   NULL,
14917                                   NULL, /* pvwv_offset */
14918                                   NULL,
14919                                   NULL,
14920                                   NULL, /* pbytes_offset */
14921                                   NULL,
14922                                   expected, ARRAY_SIZE(expected));
14923         TALLOC_FREE(subreq);
14924         if (tevent_req_nterror(req, status)) {
14925                 return;
14926         }
14927         tevent_req_done(req);
14928 }
14929
14930 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14931 {
14932         return tevent_req_simple_recv_ntstatus(req);
14933 }
14934
14935 static bool run_smb1_truncated_sesssetup(int dummy)
14936 {
14937         struct tevent_context *ev;
14938         struct tevent_req *req;
14939         struct smbXcli_conn *conn;
14940         struct sockaddr_storage ss;
14941         NTSTATUS status;
14942         int fd;
14943         bool ok;
14944
14945         printf("Starting send truncated SMB1 sesssetup.\n");
14946
14947         ok = resolve_name(host, &ss, 0x20, true);
14948         if (!ok) {
14949                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14950                 return false;
14951         }
14952
14953         status = open_socket_out(&ss, 445, 10000, &fd);
14954         if (!NT_STATUS_IS_OK(status)) {
14955                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14956                           nt_errstr(status));
14957                 return false;
14958         }
14959
14960         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14961                                    NULL, 0, NULL);
14962         if (conn == NULL) {
14963                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14964                 return false;
14965         }
14966
14967         status = smbXcli_negprot(conn,
14968                                  0,
14969                                  PROTOCOL_NT1,
14970                                  PROTOCOL_NT1,
14971                                  NULL,
14972                                  NULL,
14973                                  NULL);
14974         if (!NT_STATUS_IS_OK(status)) {
14975                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14976                 return false;
14977         }
14978
14979         ev = samba_tevent_context_init(talloc_tos());
14980         if (ev == NULL) {
14981                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14982                 return false;
14983         }
14984
14985         req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14986         if (req == NULL) {
14987                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14988                 return false;
14989         }
14990
14991         ok = tevent_req_poll_ntstatus(req, ev, &status);
14992         if (!ok) {
14993                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14994                         nt_errstr(status));
14995                 return false;
14996         }
14997
14998         status = smb1_session_setup_nt1_truncated_recv(req);
14999         if (!NT_STATUS_IS_OK(status)) {
15000                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
15001                           "%s, expected NT_STATUS_OK\n",
15002                           nt_errstr(status));
15003                 return false;
15004         }
15005
15006         TALLOC_FREE(conn);
15007         return true;
15008 }
15009
15010 struct smb1_negotiate_exit_state {
15011         int dummy;
15012 };
15013
15014 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15015
15016 static struct tevent_req *smb1_negotiate_exit_send(
15017                 TALLOC_CTX *mem_ctx,
15018                 struct tevent_context *ev,
15019                 struct smbXcli_conn *conn)
15020 {
15021         struct smb1_negotiate_exit_state *state = NULL;
15022         struct tevent_req *req = NULL;
15023         struct tevent_req *subreq = NULL;
15024
15025         req = tevent_req_create(mem_ctx,
15026                                 &state,
15027                                 struct smb1_negotiate_exit_state);
15028         if (req == NULL) {
15029                 return NULL;
15030         }
15031         subreq = smb1cli_req_send(state, ev, conn,
15032                                   SMBexit,
15033                                   0, /*  additional_flags */
15034                                   0, /*  clear_flags */
15035                                   0, /*  additional_flags2 */
15036                                   0, /*  clear_flags2 */
15037                                   10000, /* timeout_msec */
15038                                   getpid(),
15039                                   NULL, /* tcon */
15040                                   NULL, /* session */
15041                                   0, /* wct */
15042                                   NULL,
15043                                   0,
15044                                   NULL);
15045         if (tevent_req_nomem(subreq, req)) {
15046                 return tevent_req_post(req, ev);
15047         }
15048         tevent_req_set_callback(subreq,
15049                                 smb1_negotiate_exit_done,
15050                                 req);
15051         return req;
15052 }
15053
15054 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15055 {
15056         struct tevent_req *req =
15057                 tevent_req_callback_data(subreq,
15058                 struct tevent_req);
15059         struct smb1_negotiate_exit_state *state =
15060                 tevent_req_data(req,
15061                 struct smb1_negotiate_exit_state);
15062         NTSTATUS status;
15063         struct smb1cli_req_expected_response expected[] = {
15064         {
15065                 .status = NT_STATUS_OK,
15066                 .wct    = 0,
15067         },
15068         };
15069
15070         status = smb1cli_req_recv(subreq, state,
15071                                   NULL,
15072                                   NULL,
15073                                   NULL,
15074                                   NULL,
15075                                   NULL, /* pvwv_offset */
15076                                   NULL,
15077                                   NULL,
15078                                   NULL, /* pbytes_offset */
15079                                   NULL,
15080                                   expected, ARRAY_SIZE(expected));
15081         TALLOC_FREE(subreq);
15082         if (tevent_req_nterror(req, status)) {
15083                 return;
15084         }
15085         tevent_req_done(req);
15086 }
15087
15088 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15089 {
15090         return tevent_req_simple_recv_ntstatus(req);
15091 }
15092
15093 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15094                          struct tevent_context *ev,
15095                          struct smbXcli_conn *conn)
15096 {
15097         struct tevent_req *req;
15098         bool ok;
15099         NTSTATUS status;
15100         NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15101
15102         req = smb1_negotiate_exit_send(ev, ev, conn);
15103         if (req == NULL) {
15104                 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15105                 return false;
15106         }
15107
15108         ok = tevent_req_poll_ntstatus(req, ev, &status);
15109         if (!ok) {
15110                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15111                         nt_errstr(status));
15112                 return false;
15113         }
15114
15115         status = smb1_negotiate_exit_recv(req);
15116         if (!NT_STATUS_EQUAL(status, expected_status)) {
15117                 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15118                           "%s, expected ERRSRV, ERRinvnid\n",
15119                           nt_errstr(status));
15120                 return false;
15121         }
15122         return true;
15123 }
15124
15125 static bool run_smb1_negotiate_exit(int dummy)
15126 {
15127         struct tevent_context *ev;
15128         struct smbXcli_conn *conn;
15129         struct sockaddr_storage ss;
15130         NTSTATUS status;
15131         int fd;
15132         bool ok;
15133
15134         printf("Starting send SMB1 negotiate+exit.\n");
15135
15136         ok = resolve_name(host, &ss, 0x20, true);
15137         if (!ok) {
15138                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15139                 return false;
15140         }
15141
15142         status = open_socket_out(&ss, 445, 10000, &fd);
15143         if (!NT_STATUS_IS_OK(status)) {
15144                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15145                           nt_errstr(status));
15146                 return false;
15147         }
15148
15149         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15150                                    NULL, 0, NULL);
15151         if (conn == NULL) {
15152                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15153                 return false;
15154         }
15155
15156         status = smbXcli_negprot(conn,
15157                                  0,
15158                                  PROTOCOL_NT1,
15159                                  PROTOCOL_NT1,
15160                                  NULL,
15161                                  NULL,
15162                                  NULL);
15163         if (!NT_STATUS_IS_OK(status)) {
15164                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15165                 return false;
15166         }
15167
15168         ev = samba_tevent_context_init(talloc_tos());
15169         if (ev == NULL) {
15170                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15171                 return false;
15172         }
15173
15174         /*
15175          * Call do_smb1_exit twice to catch a server crash, the
15176          * server sends the first return code then crashes.
15177          */
15178         ok = do_smb1_exit(ev, ev, conn);
15179         if (!ok) {
15180                 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15181                 return false;
15182         }
15183         ok = do_smb1_exit(ev, ev, conn);
15184         if (!ok) {
15185                 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15186                 return false;
15187         }
15188
15189         TALLOC_FREE(conn);
15190         return true;
15191 }
15192
15193 static bool run_smb1_negotiate_tcon(int dummy)
15194 {
15195         struct cli_state *cli = NULL;
15196         uint16_t cnum = 0;
15197         uint16_t max_xmit = 0;
15198         NTSTATUS status;
15199
15200         printf("Starting send SMB1 negotiate+tcon.\n");
15201         cli = open_nbt_connection();
15202         if (cli == NULL) {
15203                 d_fprintf(stderr, "open_nbt_connection failed!\n");
15204                 return false;
15205         }
15206         smbXcli_conn_set_sockopt(cli->conn, sockops);
15207
15208         status = smbXcli_negprot(cli->conn,
15209                                  0,
15210                                  PROTOCOL_NT1,
15211                                  PROTOCOL_NT1,
15212                                  NULL,
15213                                  NULL,
15214                                  NULL);
15215         if (!NT_STATUS_IS_OK(status)) {
15216                 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15217                         nt_errstr(status));
15218                 return false;
15219         }
15220         status = cli_raw_tcon(cli,
15221                               share,
15222                               "",
15223                               "?????",
15224                               &max_xmit,
15225                               &cnum);
15226         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15227                 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15228                         "(should get NT_STATUS_ACCESS_DENIED)!\n",
15229                         nt_errstr(status));
15230                 return false;
15231         }
15232         return true;
15233 }
15234
15235 static bool run_ign_bad_negprot(int dummy)
15236 {
15237         struct tevent_context *ev;
15238         struct tevent_req *req;
15239         struct smbXcli_conn *conn;
15240         struct sockaddr_storage ss;
15241         NTSTATUS status;
15242         int fd;
15243         bool ok;
15244
15245         printf("starting ignore bad negprot\n");
15246
15247         ok = resolve_name(host, &ss, 0x20, true);
15248         if (!ok) {
15249                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15250                 return false;
15251         }
15252
15253         status = open_socket_out(&ss, 445, 10000, &fd);
15254         if (!NT_STATUS_IS_OK(status)) {
15255                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15256                           nt_errstr(status));
15257                 return false;
15258         }
15259
15260         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15261                                    NULL, 0, NULL);
15262         if (conn == NULL) {
15263                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15264                 return false;
15265         }
15266
15267         status = smbXcli_negprot(conn,
15268                                  0,
15269                                  PROTOCOL_CORE,
15270                                  PROTOCOL_CORE,
15271                                  NULL,
15272                                  NULL,
15273                                  NULL);
15274         if (NT_STATUS_IS_OK(status)) {
15275                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15276                 return false;
15277         }
15278
15279         ev = samba_tevent_context_init(talloc_tos());
15280         if (ev == NULL) {
15281                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15282                 return false;
15283         }
15284
15285         req = smb1cli_session_setup_nt1_send(
15286                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15287                 data_blob_null, data_blob_null, 0x40,
15288                 "Windows 2000 2195", "Windows 2000 5.0");
15289         if (req == NULL) {
15290                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15291                 return false;
15292         }
15293
15294         ok = tevent_req_poll_ntstatus(req, ev, &status);
15295         if (!ok) {
15296                 d_fprintf(stderr, "tevent_req_poll failed\n");
15297                 return false;
15298         }
15299
15300         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15301                                                 NULL, NULL);
15302         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15303                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15304                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
15305                           nt_errstr(status));
15306                 return false;
15307         }
15308
15309         TALLOC_FREE(conn);
15310
15311         printf("starting ignore bad negprot\n");
15312
15313         return true;
15314 }
15315
15316
15317 static double create_procs(bool (*fn)(int), bool *result)
15318 {
15319         int i, status;
15320         volatile pid_t *child_status;
15321         volatile bool *child_status_out;
15322         int synccount;
15323         int tries = 8;
15324         struct timeval start;
15325
15326         synccount = 0;
15327
15328         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15329         if (!child_status) {
15330                 printf("Failed to setup shared memory\n");
15331                 return -1;
15332         }
15333
15334         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15335         if (!child_status_out) {
15336                 printf("Failed to setup result status shared memory\n");
15337                 return -1;
15338         }
15339
15340         for (i = 0; i < torture_nprocs; i++) {
15341                 child_status[i] = 0;
15342                 child_status_out[i] = True;
15343         }
15344
15345         start = timeval_current();
15346
15347         for (i=0;i<torture_nprocs;i++) {
15348                 procnum = i;
15349                 if (fork() == 0) {
15350                         pid_t mypid = getpid();
15351                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15352
15353                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
15354
15355                         while (1) {
15356                                 if (torture_open_connection(&current_cli, i)) break;
15357                                 if (tries-- == 0) {
15358                                         printf("pid %d failed to start\n", (int)getpid());
15359                                         _exit(1);
15360                                 }
15361                                 smb_msleep(10);
15362                         }
15363
15364                         child_status[i] = getpid();
15365
15366                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15367
15368                         child_status_out[i] = fn(i);
15369                         _exit(0);
15370                 }
15371         }
15372
15373         do {
15374                 synccount = 0;
15375                 for (i=0;i<torture_nprocs;i++) {
15376                         if (child_status[i]) synccount++;
15377                 }
15378                 if (synccount == torture_nprocs) break;
15379                 smb_msleep(10);
15380         } while (timeval_elapsed(&start) < 30);
15381
15382         if (synccount != torture_nprocs) {
15383                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15384                 *result = False;
15385                 return timeval_elapsed(&start);
15386         }
15387
15388         /* start the client load */
15389         start = timeval_current();
15390
15391         for (i=0;i<torture_nprocs;i++) {
15392                 child_status[i] = 0;
15393         }
15394
15395         printf("%d clients started\n", torture_nprocs);
15396
15397         for (i=0;i<torture_nprocs;i++) {
15398                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15399         }
15400
15401         printf("\n");
15402
15403         for (i=0;i<torture_nprocs;i++) {
15404                 if (!child_status_out[i]) {
15405                         *result = False;
15406                 }
15407         }
15408         return timeval_elapsed(&start);
15409 }
15410
15411 #define FLAG_MULTIPROC 1
15412
15413 static struct {
15414         const char *name;
15415         bool (*fn)(int);
15416         unsigned flags;
15417 } torture_ops[] = {
15418         {
15419                 .name = "FDPASS",
15420                 .fn   = run_fdpasstest,
15421         },
15422         {
15423                 .name = "LOCK1",
15424                 .fn   = run_locktest1,
15425         },
15426         {
15427                 .name = "LOCK2",
15428                 .fn   =  run_locktest2,
15429         },
15430         {
15431                 .name = "LOCK3",
15432                 .fn   =  run_locktest3,
15433         },
15434         {
15435                 .name = "LOCK4",
15436                 .fn   =  run_locktest4,
15437         },
15438         {
15439                 .name = "LOCK5",
15440                 .fn   =  run_locktest5,
15441         },
15442         {
15443                 .name = "LOCK6",
15444                 .fn   =  run_locktest6,
15445         },
15446         {
15447                 .name = "LOCK7",
15448                 .fn   =  run_locktest7,
15449         },
15450         {
15451                 .name = "LOCK8",
15452                 .fn   =  run_locktest8,
15453         },
15454         {
15455                 .name = "LOCK9A",
15456                 .fn   =  run_locktest9a,
15457         },
15458         {
15459                 .name = "LOCK9B",
15460                 .fn   =  run_locktest9b,
15461         },
15462         {
15463                 .name = "LOCK10",
15464                 .fn   =  run_locktest10,
15465         },
15466         {
15467                 .name = "LOCK11",
15468                 .fn   =  run_locktest11,
15469         },
15470         {
15471                 .name = "LOCK12",
15472                 .fn   =  run_locktest12,
15473         },
15474         {
15475                 .name = "LOCK13",
15476                 .fn   =  run_locktest13,
15477         },
15478         {
15479                 .name = "UNLINK",
15480                 .fn   = run_unlinktest,
15481         },
15482         {
15483                 .name = "BROWSE",
15484                 .fn   = run_browsetest,
15485         },
15486         {
15487                 .name = "ATTR",
15488                 .fn   =   run_attrtest,
15489         },
15490         {
15491                 .name = "TRANS2",
15492                 .fn   = run_trans2test,
15493         },
15494         {
15495                 .name  = "MAXFID",
15496                 .fn    = run_maxfidtest,
15497                 .flags = FLAG_MULTIPROC,
15498         },
15499         {
15500                 .name  = "TORTURE",
15501                 .fn    = run_torture,
15502                 .flags = FLAG_MULTIPROC,
15503         },
15504         {
15505                 .name  = "RANDOMIPC",
15506                 .fn    = run_randomipc,
15507         },
15508         {
15509                 .name  = "NEGNOWAIT",
15510                 .fn    = run_negprot_nowait,
15511         },
15512         {
15513                 .name  = "NBENCH",
15514                 .fn    =  run_nbench,
15515         },
15516         {
15517                 .name  = "NBENCH2",
15518                 .fn    = run_nbench2,
15519         },
15520         {
15521                 .name  = "OPLOCK1",
15522                 .fn    =  run_oplock1,
15523         },
15524         {
15525                 .name  = "OPLOCK2",
15526                 .fn    =  run_oplock2,
15527         },
15528         {
15529                 .name  = "OPLOCK4",
15530                 .fn    =  run_oplock4,
15531         },
15532 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15533         {
15534                 .name  = "OPLOCK5",
15535                 .fn    =  run_oplock5,
15536         },
15537 #endif
15538         {
15539                 .name  = "DIR",
15540                 .fn    =  run_dirtest,
15541         },
15542         {
15543                 .name  = "DIR1",
15544                 .fn    =  run_dirtest1,
15545         },
15546         {
15547                 .name  = "DIR-CREATETIME",
15548                 .fn    =  run_dir_createtime,
15549         },
15550         {
15551                 .name  = "DENY1",
15552                 .fn    =  torture_denytest1,
15553         },
15554         {
15555                 .name  = "DENY2",
15556                 .fn    =  torture_denytest2,
15557         },
15558         {
15559                 .name  = "TCON",
15560                 .fn    =  run_tcon_test,
15561         },
15562         {
15563                 .name  = "TCONDEV",
15564                 .fn    =  run_tcon_devtype_test,
15565         },
15566         {
15567                 .name  = "RW1",
15568                 .fn    =  run_readwritetest,
15569         },
15570         {
15571                 .name  = "RW2",
15572                 .fn    =  run_readwritemulti,
15573                 .flags = FLAG_MULTIPROC
15574         },
15575         {
15576                 .name  = "RW3",
15577                 .fn    =  run_readwritelarge,
15578         },
15579         {
15580                 .name  = "RW-SIGNING",
15581                 .fn    =  run_readwritelarge_signtest,
15582         },
15583         {
15584                 .name  = "OPEN",
15585                 .fn    = run_opentest,
15586         },
15587         {
15588                 .name  = "POSIX",
15589                 .fn    = run_simple_posix_open_test,
15590         },
15591         {
15592                 .name  = "POSIX-APPEND",
15593                 .fn    = run_posix_append,
15594         },
15595         {
15596                 .name  = "POSIX-SYMLINK-ACL",
15597                 .fn    = run_acl_symlink_test,
15598         },
15599         {
15600                 .name  = "POSIX-SYMLINK-EA",
15601                 .fn    = run_ea_symlink_test,
15602         },
15603         {
15604                 .name  = "POSIX-STREAM-DELETE",
15605                 .fn    = run_posix_stream_delete,
15606         },
15607         {
15608                 .name  = "POSIX-OFD-LOCK",
15609                 .fn    = run_posix_ofd_lock_test,
15610         },
15611         {
15612                 .name  = "POSIX-BLOCKING-LOCK",
15613                 .fn    = run_posix_blocking_lock,
15614         },
15615         {
15616                 .name  = "POSIX-MKDIR",
15617                 .fn    = run_posix_mkdir_test,
15618         },
15619         {
15620                 .name  = "POSIX-ACL-OPLOCK",
15621                 .fn    = run_posix_acl_oplock_test,
15622         },
15623         {
15624                 .name  = "POSIX-ACL-SHAREROOT",
15625                 .fn    = run_posix_acl_shareroot_test,
15626         },
15627         {
15628                 .name  = "POSIX-LS-WILDCARD",
15629                 .fn    = run_posix_ls_wildcard_test,
15630         },
15631         {
15632                 .name  = "POSIX-LS-SINGLE",
15633                 .fn    = run_posix_ls_single_test,
15634         },
15635         {
15636                 .name  = "POSIX-READLINK",
15637                 .fn    = run_posix_readlink_test,
15638         },
15639         {
15640                 .name  = "POSIX-STAT",
15641                 .fn    = run_posix_stat_test,
15642         },
15643         {
15644                 .name  = "POSIX-SYMLINK-PARENT",
15645                 .fn    = run_posix_symlink_parent_test,
15646         },
15647         {
15648                 .name  = "POSIX-SYMLINK-CHMOD",
15649                 .fn    = run_posix_symlink_chmod_test,
15650         },
15651         {
15652                 .name  = "POSIX-SYMLINK-RENAME",
15653                 .fn    = run_posix_symlink_rename_test,
15654         },
15655         {
15656                 .name  = "POSIX-DIR-DEFAULT-ACL",
15657                 .fn    = run_posix_dir_default_acl_test,
15658         },
15659         {
15660                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15661                 .fn    = run_posix_symlink_getpathinfo_test,
15662         },
15663         {
15664                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15665                 .fn    = run_posix_symlink_setpathinfo_test,
15666         },
15667         {
15668                 .name  = "WINDOWS-BAD-SYMLINK",
15669                 .fn    = run_symlink_open_test,
15670         },
15671         {
15672                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15673                 .fn    = run_smb1_wild_mangle_unlink_test,
15674         },
15675         {
15676                 .name  = "SMB1-WILD-MANGLE-RENAME",
15677                 .fn    = run_smb1_wild_mangle_rename_test,
15678         },
15679         {
15680                 .name  = "CASE-INSENSITIVE-CREATE",
15681                 .fn    = run_case_insensitive_create,
15682         },
15683         {
15684                 .name  = "ASYNC-ECHO",
15685                 .fn    = run_async_echo,
15686         },
15687         {
15688                 .name  = "UID-REGRESSION-TEST",
15689                 .fn    = run_uid_regression_test,
15690         },
15691         {
15692                 .name  = "SHORTNAME-TEST",
15693                 .fn    = run_shortname_test,
15694         },
15695         {
15696                 .name  = "ADDRCHANGE",
15697                 .fn    = run_addrchange,
15698         },
15699 #if 1
15700         {
15701                 .name  = "OPENATTR",
15702                 .fn    = run_openattrtest,
15703         },
15704 #endif
15705         {
15706                 .name  = "XCOPY",
15707                 .fn    = run_xcopy,
15708         },
15709         {
15710                 .name  = "RENAME",
15711                 .fn    = run_rename,
15712         },
15713         {
15714                 .name  = "RENAME-ACCESS",
15715                 .fn    = run_rename_access,
15716         },
15717         {
15718                 .name  = "OWNER-RIGHTS",
15719                 .fn    = run_owner_rights,
15720         },
15721         {
15722                 .name  = "DELETE",
15723                 .fn    = run_deletetest,
15724         },
15725         {
15726                 .name  = "DELETE-STREAM",
15727                 .fn    = run_delete_stream,
15728         },
15729         {
15730                 .name  = "DELETE-PRINT",
15731                 .fn    = run_delete_print_test,
15732         },
15733         {
15734                 .name  = "DELETE-LN",
15735                 .fn    = run_deletetest_ln,
15736         },
15737         {
15738                 .name  = "PROPERTIES",
15739                 .fn    = run_properties,
15740         },
15741         {
15742                 .name  = "MANGLE",
15743                 .fn    = torture_mangle,
15744         },
15745         {
15746                 .name  = "MANGLE1",
15747                 .fn    = run_mangle1,
15748         },
15749         {
15750                 .name  = "MANGLE-ILLEGAL",
15751                 .fn    = run_mangle_illegal,
15752         },
15753         {
15754                 .name  = "W2K",
15755                 .fn    = run_w2ktest,
15756         },
15757         {
15758                 .name  = "TRANS2SCAN",
15759                 .fn    = torture_trans2_scan,
15760         },
15761         {
15762                 .name  = "NTTRANSSCAN",
15763                 .fn    = torture_nttrans_scan,
15764         },
15765         {
15766                 .name  = "UTABLE",
15767                 .fn    = torture_utable,
15768         },
15769         {
15770                 .name  = "CASETABLE",
15771                 .fn    = torture_casetable,
15772         },
15773         {
15774                 .name  = "ERRMAPEXTRACT",
15775                 .fn    = run_error_map_extract,
15776         },
15777         {
15778                 .name  = "PIPE_NUMBER",
15779                 .fn    = run_pipe_number,
15780         },
15781         {
15782                 .name  = "TCON2",
15783                 .fn    =  run_tcon2_test,
15784         },
15785         {
15786                 .name  = "IOCTL",
15787                 .fn    =  torture_ioctl_test,
15788         },
15789         {
15790                 .name  = "CHKPATH",
15791                 .fn    =  torture_chkpath_test,
15792         },
15793         {
15794                 .name  = "FDSESS",
15795                 .fn    = run_fdsesstest,
15796         },
15797         {
15798                 .name  = "EATEST",
15799                 .fn    = run_eatest,
15800         },
15801         {
15802                 .name  = "SESSSETUP_BENCH",
15803                 .fn    = run_sesssetup_bench,
15804         },
15805         {
15806                 .name  = "CHAIN1",
15807                 .fn    = run_chain1,
15808         },
15809         {
15810                 .name  = "CHAIN2",
15811                 .fn    = run_chain2,
15812         },
15813         {
15814                 .name  = "CHAIN3",
15815                 .fn    = run_chain3,
15816         },
15817         {
15818                 .name  = "WINDOWS-WRITE",
15819                 .fn    = run_windows_write,
15820         },
15821         {
15822                 .name  = "LARGE_READX",
15823                 .fn    = run_large_readx,
15824         },
15825         {
15826                 .name  = "MSDFS-ATTRIBUTE",
15827                 .fn    = run_msdfs_attribute,
15828         },
15829         {
15830                 .name  = "NTTRANS-CREATE",
15831                 .fn    = run_nttrans_create,
15832         },
15833         {
15834                 .name  = "NTTRANS-FSCTL",
15835                 .fn    = run_nttrans_fsctl,
15836         },
15837         {
15838                 .name  = "CLI_ECHO",
15839                 .fn    = run_cli_echo,
15840         },
15841         {
15842                 .name  = "CLI_SPLICE",
15843                 .fn    = run_cli_splice,
15844         },
15845         {
15846                 .name  = "TLDAP",
15847                 .fn    = run_tldap,
15848         },
15849         {
15850                 .name  = "STREAMERROR",
15851                 .fn    = run_streamerror,
15852         },
15853         {
15854                 .name  = "NOTIFY-BENCH",
15855                 .fn    = run_notify_bench,
15856         },
15857         {
15858                 .name  = "NOTIFY-BENCH2",
15859                 .fn    = run_notify_bench2,
15860         },
15861         {
15862                 .name  = "NOTIFY-BENCH3",
15863                 .fn    = run_notify_bench3,
15864         },
15865         {
15866                 .name  = "BAD-NBT-SESSION",
15867                 .fn    = run_bad_nbt_session,
15868         },
15869         {
15870                 .name  = "IGN-BAD-NEGPROT",
15871                 .fn    = run_ign_bad_negprot,
15872         },
15873         {
15874                 .name  = "SMB-ANY-CONNECT",
15875                 .fn    = run_smb_any_connect,
15876         },
15877         {
15878                 .name  = "NOTIFY-ONLINE",
15879                 .fn    = run_notify_online,
15880         },
15881         {
15882                 .name  = "SMB2-BASIC",
15883                 .fn    = run_smb2_basic,
15884         },
15885         {
15886                 .name  = "SMB2-NEGPROT",
15887                 .fn    = run_smb2_negprot,
15888         },
15889         {
15890                 .name  = "SMB2-ANONYMOUS",
15891                 .fn    = run_smb2_anonymous,
15892         },
15893         {
15894                 .name  = "SMB2-SESSION-RECONNECT",
15895                 .fn    = run_smb2_session_reconnect,
15896         },
15897         {
15898                 .name  = "SMB2-TCON-DEPENDENCE",
15899                 .fn    = run_smb2_tcon_dependence,
15900         },
15901         {
15902                 .name  = "SMB2-MULTI-CHANNEL",
15903                 .fn    = run_smb2_multi_channel,
15904         },
15905         {
15906                 .name  = "SMB2-SESSION-REAUTH",
15907                 .fn    = run_smb2_session_reauth,
15908         },
15909         {
15910                 .name  = "SMB2-FTRUNCATE",
15911                 .fn    = run_smb2_ftruncate,
15912         },
15913         {
15914                 .name  = "SMB2-DIR-FSYNC",
15915                 .fn    = run_smb2_dir_fsync,
15916         },
15917         {
15918                 .name  = "SMB2-PATH-SLASH",
15919                 .fn    = run_smb2_path_slash,
15920         },
15921         {
15922                 .name  = "SMB1-SYSTEM-SECURITY",
15923                 .fn    = run_smb1_system_security,
15924         },
15925         {
15926                 .name  = "SMB2-SACL",
15927                 .fn    = run_smb2_sacl,
15928         },
15929         {
15930                 .name  = "SMB2-QUOTA1",
15931                 .fn    = run_smb2_quota1,
15932         },
15933         {
15934                 .name  = "SMB2-INVALID-PIPENAME",
15935                 .fn    = run_smb2_invalid_pipename,
15936         },
15937         {
15938                 .name  = "SMB2-STREAM-ACL",
15939                 .fn    = run_smb2_stream_acl,
15940         },
15941         {
15942                 .name  = "SMB2-LIST-DIR-ASYNC",
15943                 .fn    = run_list_dir_async_test,
15944         },
15945         {
15946                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15947                 .fn    = run_delete_on_close_non_empty,
15948         },
15949         {
15950                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15951                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15952         },
15953         {
15954                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15955                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15956         },
15957         {
15958                 .name  = "SMB2-DFS-PATHS",
15959                 .fn    = run_smb2_dfs_paths,
15960         },
15961         {
15962                 .name  = "SMB2-NON-DFS-SHARE",
15963                 .fn    = run_smb2_non_dfs_share,
15964         },
15965         {
15966                 .name  = "SMB2-DFS-SHARE-NON-DFS-PATH",
15967                 .fn    = run_smb2_dfs_share_non_dfs_path,
15968         },
15969         {
15970                 .name  = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15971                 .fn    = run_smb2_dfs_filename_leading_backslash,
15972         },
15973         {
15974                 .name  = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15975                 .fn    = run_smb2_pipe_read_async_disconnect,
15976         },
15977         {
15978                 .name  = "SMB1-TRUNCATED-SESSSETUP",
15979                 .fn    = run_smb1_truncated_sesssetup,
15980         },
15981         {
15982                 .name  = "SMB1-NEGOTIATE-EXIT",
15983                 .fn    = run_smb1_negotiate_exit,
15984         },
15985         {
15986                 .name  = "SMB1-NEGOTIATE-TCON",
15987                 .fn    = run_smb1_negotiate_tcon,
15988         },
15989         {
15990                 .name  = "SMB1-DFS-PATHS",
15991                 .fn    = run_smb1_dfs_paths,
15992         },
15993         {
15994                 .name  = "SMB1-DFS-SEARCH-PATHS",
15995                 .fn    = run_smb1_dfs_search_paths,
15996         },
15997         {
15998                 .name  = "SMB1-DFS-OPERATIONS",
15999                 .fn    = run_smb1_dfs_operations,
16000         },
16001         {
16002                 .name  = "SMB1-DFS-BADPATH",
16003                 .fn    = run_smb1_dfs_check_badpath,
16004         },
16005         {
16006                 .name  = "CLEANUP1",
16007                 .fn    = run_cleanup1,
16008         },
16009         {
16010                 .name  = "CLEANUP2",
16011                 .fn    = run_cleanup2,
16012         },
16013         {
16014                 .name  = "CLEANUP4",
16015                 .fn    = run_cleanup4,
16016         },
16017         {
16018                 .name  = "OPLOCK-CANCEL",
16019                 .fn    = run_oplock_cancel,
16020         },
16021         {
16022                 .name  = "PIDHIGH",
16023                 .fn    = run_pidhigh,
16024         },
16025         {
16026                 .name  = "LOCAL-SUBSTITUTE",
16027                 .fn    = run_local_substitute,
16028         },
16029         {
16030                 .name  = "LOCAL-GENCACHE",
16031                 .fn    = run_local_gencache,
16032         },
16033         {
16034                 .name  = "LOCAL-DBWRAP-WATCH1",
16035                 .fn    = run_dbwrap_watch1,
16036         },
16037         {
16038                 .name  = "LOCAL-DBWRAP-WATCH2",
16039                 .fn    = run_dbwrap_watch2,
16040         },
16041         {
16042                 .name  = "LOCAL-DBWRAP-WATCH3",
16043                 .fn    = run_dbwrap_watch3,
16044         },
16045         {
16046                 .name  = "LOCAL-DBWRAP-WATCH4",
16047                 .fn    = run_dbwrap_watch4,
16048         },
16049         {
16050                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
16051                 .fn    = run_dbwrap_do_locked1,
16052         },
16053         {
16054                 .name  = "LOCAL-MESSAGING-READ1",
16055                 .fn    = run_messaging_read1,
16056         },
16057         {
16058                 .name  = "LOCAL-MESSAGING-READ2",
16059                 .fn    = run_messaging_read2,
16060         },
16061         {
16062                 .name  = "LOCAL-MESSAGING-READ3",
16063                 .fn    = run_messaging_read3,
16064         },
16065         {
16066                 .name  = "LOCAL-MESSAGING-READ4",
16067                 .fn    = run_messaging_read4,
16068         },
16069         {
16070                 .name  = "LOCAL-MESSAGING-FDPASS1",
16071                 .fn    = run_messaging_fdpass1,
16072         },
16073         {
16074                 .name  = "LOCAL-MESSAGING-FDPASS2",
16075                 .fn    = run_messaging_fdpass2,
16076         },
16077         {
16078                 .name  = "LOCAL-MESSAGING-FDPASS2a",
16079                 .fn    = run_messaging_fdpass2a,
16080         },
16081         {
16082                 .name  = "LOCAL-MESSAGING-FDPASS2b",
16083                 .fn    = run_messaging_fdpass2b,
16084         },
16085         {
16086                 .name  = "LOCAL-MESSAGING-SEND-ALL",
16087                 .fn    = run_messaging_send_all,
16088         },
16089         {
16090                 .name  = "LOCAL-BASE64",
16091                 .fn    = run_local_base64,
16092         },
16093         {
16094                 .name  = "LOCAL-RBTREE",
16095                 .fn    = run_local_rbtree,
16096         },
16097         {
16098                 .name  = "LOCAL-MEMCACHE",
16099                 .fn    = run_local_memcache,
16100         },
16101         {
16102                 .name  = "LOCAL-STREAM-NAME",
16103                 .fn    = run_local_stream_name,
16104         },
16105         {
16106                 .name  = "LOCAL-STR-MATCH-MSWILD",
16107                 .fn    = run_str_match_mswild,
16108         },
16109         {
16110                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
16111                 .fn    = run_str_match_regex_sub1,
16112         },
16113         {
16114                 .name  = "WBCLIENT-MULTI-PING",
16115                 .fn    = run_wbclient_multi_ping,
16116         },
16117         {
16118                 .name  = "LOCAL-string_to_sid",
16119                 .fn    = run_local_string_to_sid,
16120         },
16121         {
16122                 .name  = "LOCAL-sid_to_string",
16123                 .fn    = run_local_sid_to_string,
16124         },
16125         {
16126                 .name  = "LOCAL-binary_to_sid",
16127                 .fn    = run_local_binary_to_sid,
16128         },
16129         {
16130                 .name  = "LOCAL-DBTRANS",
16131                 .fn    = run_local_dbtrans,
16132         },
16133         {
16134                 .name  = "LOCAL-TEVENT-POLL",
16135                 .fn    = run_local_tevent_poll,
16136         },
16137         {
16138                 .name  = "LOCAL-CONVERT-STRING",
16139                 .fn    = run_local_convert_string,
16140         },
16141         {
16142                 .name  = "LOCAL-CONV-AUTH-INFO",
16143                 .fn    = run_local_conv_auth_info,
16144         },
16145         {
16146                 .name  = "LOCAL-hex_encode_buf",
16147                 .fn    = run_local_hex_encode_buf,
16148         },
16149         {
16150                 .name  = "LOCAL-IDMAP-TDB-COMMON",
16151                 .fn    = run_idmap_tdb_common_test,
16152         },
16153         {
16154                 .name  = "LOCAL-remove_duplicate_addrs2",
16155                 .fn    = run_local_remove_duplicate_addrs2,
16156         },
16157         {
16158                 .name  = "local-tdb-opener",
16159                 .fn    = run_local_tdb_opener,
16160         },
16161         {
16162                 .name  = "local-tdb-writer",
16163                 .fn    = run_local_tdb_writer,
16164         },
16165         {
16166                 .name  = "LOCAL-DBWRAP-CTDB1",
16167                 .fn    = run_local_dbwrap_ctdb1,
16168         },
16169         {
16170                 .name  = "LOCAL-BENCH-PTHREADPOOL",
16171                 .fn    = run_bench_pthreadpool,
16172         },
16173         {
16174                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
16175                 .fn    = run_pthreadpool_tevent,
16176         },
16177         {
16178                 .name  = "LOCAL-G-LOCK1",
16179                 .fn    = run_g_lock1,
16180         },
16181         {
16182                 .name  = "LOCAL-G-LOCK2",
16183                 .fn    = run_g_lock2,
16184         },
16185         {
16186                 .name  = "LOCAL-G-LOCK3",
16187                 .fn    = run_g_lock3,
16188         },
16189         {
16190                 .name  = "LOCAL-G-LOCK4",
16191                 .fn    = run_g_lock4,
16192         },
16193         {
16194                 .name  = "LOCAL-G-LOCK4A",
16195                 .fn    = run_g_lock4a,
16196         },
16197         {
16198                 .name  = "LOCAL-G-LOCK5",
16199                 .fn    = run_g_lock5,
16200         },
16201         {
16202                 .name  = "LOCAL-G-LOCK6",
16203                 .fn    = run_g_lock6,
16204         },
16205         {
16206                 .name  = "LOCAL-G-LOCK7",
16207                 .fn    = run_g_lock7,
16208         },
16209         {
16210                 .name  = "LOCAL-G-LOCK8",
16211                 .fn    = run_g_lock8,
16212         },
16213         {
16214                 .name  = "LOCAL-G-LOCK-PING-PONG",
16215                 .fn    = run_g_lock_ping_pong,
16216         },
16217         {
16218                 .name  = "LOCAL-CANONICALIZE-PATH",
16219                 .fn    = run_local_canonicalize_path,
16220         },
16221         {
16222                 .name  = "LOCAL-NAMEMAP-CACHE1",
16223                 .fn    = run_local_namemap_cache1,
16224         },
16225         {
16226                 .name  = "LOCAL-IDMAP-CACHE1",
16227                 .fn    = run_local_idmap_cache1,
16228         },
16229         {
16230                 .name  = "qpathinfo-bufsize",
16231                 .fn    = run_qpathinfo_bufsize,
16232         },
16233         {
16234                 .name  = "hide-new-files-timeout",
16235                 .fn    = run_hidenewfiles,
16236         },
16237         {
16238                 .name  = "hide-new-files-timeout-showdirs",
16239                 .fn    = run_hidenewfiles_showdirs,
16240         },
16241 #ifdef CLUSTER_SUPPORT
16242         {
16243                 .name  = "ctdbd-conn1",
16244                 .fn    = run_ctdbd_conn1,
16245         },
16246 #endif
16247         {
16248                 .name  = "readdir-timestamp",
16249                 .fn    = run_readdir_timestamp,
16250         },
16251         {
16252                 .name  = "rpc-scale",
16253                 .fn    = run_rpc_scale,
16254         },
16255         {
16256                 .name  = "LOCAL-TDB-VALIDATE",
16257                 .fn    = run_tdb_validate,
16258         },
16259         {
16260                 .name = NULL,
16261         },
16262 };
16263
16264 /****************************************************************************
16265 run a specified test or "ALL"
16266 ****************************************************************************/
16267 static bool run_test(const char *name)
16268 {
16269         bool ret = True;
16270         bool result = True;
16271         bool found = False;
16272         int i;
16273         double t;
16274         if (strequal(name,"ALL")) {
16275                 for (i=0;torture_ops[i].name;i++) {
16276                         run_test(torture_ops[i].name);
16277                 }
16278                 found = True;
16279         }
16280
16281         for (i=0;torture_ops[i].name;i++) {
16282                 fstr_sprintf(randomfname, "\\XX%x",
16283                          (unsigned)random());
16284
16285                 if (strequal(name, torture_ops[i].name)) {
16286                         found = True;
16287                         printf("Running %s\n", name);
16288                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
16289                                 t = create_procs(torture_ops[i].fn, &result);
16290                                 if (!result) {
16291                                         ret = False;
16292                                         printf("TEST %s FAILED!\n", name);
16293                                 }
16294                         } else {
16295                                 struct timeval start;
16296                                 start = timeval_current();
16297                                 if (!torture_ops[i].fn(0)) {
16298                                         ret = False;
16299                                         printf("TEST %s FAILED!\n", name);
16300                                 }
16301                                 t = timeval_elapsed(&start);
16302                         }
16303                         printf("%s took %g secs\n\n", name, t);
16304                 }
16305         }
16306
16307         if (!found) {
16308                 printf("Did not find a test named %s\n", name);
16309                 ret = False;
16310         }
16311
16312         return ret;
16313 }
16314
16315
16316 static void usage(void)
16317 {
16318         int i;
16319
16320         printf("WARNING samba4 test suite is much more complete nowadays.\n");
16321         printf("Please use samba4 torture.\n\n");
16322
16323         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16324
16325         printf("\t-d debuglevel\n");
16326         printf("\t-U user%%pass\n");
16327         printf("\t-k                    use kerberos\n");
16328         printf("\t-N numprocs\n");
16329         printf("\t-n my_netbios_name\n");
16330         printf("\t-W workgroup\n");
16331         printf("\t-o num_operations\n");
16332         printf("\t-O socket_options\n");
16333         printf("\t-m maximum protocol\n");
16334         printf("\t-L use oplocks\n");
16335         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
16336         printf("\t-A showall\n");
16337         printf("\t-p port\n");
16338         printf("\t-s seed\n");
16339         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
16340         printf("\t-f filename           filename to test\n");
16341         printf("\t-e                    encrypt\n");
16342         printf("\t-T 'OPTION=VALUE'     smb.conf option line\n");
16343         printf("\n\n");
16344
16345         printf("tests are:");
16346         for (i=0;torture_ops[i].name;i++) {
16347                 printf(" %s", torture_ops[i].name);
16348         }
16349         printf("\n");
16350
16351         printf("default test is ALL\n");
16352
16353         exit(1);
16354 }
16355
16356 /****************************************************************************
16357   main program
16358 ****************************************************************************/
16359  int main(int argc,char *argv[])
16360 {
16361         int opt, i;
16362         char *p;
16363         int gotuser = 0;
16364         int gotpass = 0;
16365         bool correct = True;
16366         TALLOC_CTX *frame = talloc_stackframe();
16367         int seed = time(NULL);
16368         struct loadparm_context *lp_ctx = NULL;
16369
16370 #ifdef HAVE_SETBUFFER
16371         setbuffer(stdout, NULL, 0);
16372 #endif
16373
16374         setup_logging("smbtorture", DEBUG_STDOUT);
16375
16376         smb_init_locale();
16377         fault_setup();
16378
16379         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16380         if (lp_ctx == NULL) {
16381                 fprintf(stderr,
16382                         "Failed to initialise the global parameter structure.\n");
16383                 return 1;
16384         }
16385
16386         if (is_default_dyn_CONFIGFILE()) {
16387                 if(getenv("SMB_CONF_PATH")) {
16388                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16389                 }
16390         }
16391         lp_load_global(get_dyn_CONFIGFILE());
16392         load_interfaces();
16393
16394         if (argc < 2) {
16395                 usage();
16396         }
16397
16398         for(p = argv[1]; *p; p++)
16399           if(*p == '\\')
16400             *p = '/';
16401
16402         if (strncmp(argv[1], "//", 2)) {
16403                 usage();
16404         }
16405
16406         fstrcpy(host, &argv[1][2]);
16407         p = strchr_m(&host[2],'/');
16408         if (!p) {
16409                 usage();
16410         }
16411         *p = 0;
16412         fstrcpy(share, p+1);
16413
16414         fstrcpy(myname, get_myname(talloc_tos()));
16415         if (!*myname) {
16416                 fprintf(stderr, "Failed to get my hostname.\n");
16417                 return 1;
16418         }
16419
16420         if (*username == 0 && getenv("LOGNAME")) {
16421           fstrcpy(username,getenv("LOGNAME"));
16422         }
16423
16424         argc--;
16425         argv++;
16426
16427         fstrcpy(workgroup, lp_workgroup());
16428
16429         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16430                != EOF) {
16431                 switch (opt) {
16432                 case 'p':
16433                         port_to_use = atoi(optarg);
16434                         break;
16435                 case 's':
16436                         seed = atoi(optarg);
16437                         break;
16438                 case 'W':
16439                         fstrcpy(workgroup,optarg);
16440                         break;
16441                 case 'm':
16442                         lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16443                         break;
16444                 case 'N':
16445                         torture_nprocs = atoi(optarg);
16446                         break;
16447                 case 'o':
16448                         torture_numops = atoi(optarg);
16449                         break;
16450                 case 'd':
16451                         lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16452                         break;
16453                 case 'O':
16454                         sockops = optarg;
16455                         break;
16456                 case 'L':
16457                         use_oplocks = True;
16458                         break;
16459                 case 'l':
16460                         local_path = optarg;
16461                         break;
16462                 case 'A':
16463                         torture_showall = True;
16464                         break;
16465                 case 'n':
16466                         fstrcpy(myname, optarg);
16467                         break;
16468                 case 'c':
16469                         client_txt = optarg;
16470                         break;
16471                 case 'e':
16472                         do_encrypt = true;
16473                         break;
16474                 case 'k':
16475 #ifdef HAVE_KRB5
16476                         use_kerberos = True;
16477 #else
16478                         d_printf("No kerberos support compiled in\n");
16479                         exit(1);
16480 #endif
16481                         break;
16482                 case 'U':
16483                         gotuser = 1;
16484                         fstrcpy(username,optarg);
16485                         p = strchr_m(username,'%');
16486                         if (p) {
16487                                 *p = 0;
16488                                 fstrcpy(password, p+1);
16489                                 gotpass = 1;
16490                         }
16491                         break;
16492                 case 'b':
16493                         fstrcpy(multishare_conn_fname, optarg);
16494                         use_multishare_conn = True;
16495                         break;
16496                 case 'B':
16497                         torture_blocksize = atoi(optarg);
16498                         break;
16499                 case 'f':
16500                         test_filename = SMB_STRDUP(optarg);
16501                         break;
16502                 case 'T':
16503                         lpcfg_set_option(lp_ctx, optarg);
16504                         break;
16505                 default:
16506                         printf("Unknown option %c (%d)\n", (char)opt, opt);
16507                         usage();
16508                 }
16509         }
16510
16511         d_printf("using seed %d\n", seed);
16512
16513         srandom(seed);
16514
16515         if(use_kerberos && !gotuser) gotpass = True;
16516
16517         while (!gotpass) {
16518                 char pwd[256] = {0};
16519                 int rc;
16520
16521                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16522                 if (rc == 0) {
16523                         fstrcpy(password, pwd);
16524                         gotpass = 1;
16525                 }
16526         }
16527
16528         printf("host=%s share=%s user=%s myname=%s\n",
16529                host, share, username, myname);
16530
16531         torture_creds = cli_session_creds_init(frame,
16532                                                username,
16533                                                workgroup,
16534                                                NULL, /* realm */
16535                                                password,
16536                                                use_kerberos,
16537                                                false, /* fallback_after_kerberos */
16538                                                false, /* use_ccache */
16539                                                false); /* password_is_nt_hash */
16540         if (torture_creds == NULL) {
16541                 d_printf("cli_session_creds_init() failed.\n");
16542                 exit(1);
16543         }
16544
16545         if (argc == optind) {
16546                 correct = run_test("ALL");
16547         } else {
16548                 for (i=optind;i<argc;i++) {
16549                         if (!run_test(argv[i])) {
16550                                 correct = False;
16551                         }
16552                 }
16553         }
16554
16555         TALLOC_FREE(frame);
16556
16557         if (correct) {
16558                 return(0);
16559         } else {
16560                 return(1);
16561         }
16562 }