s3:torture: add '-T 'option=value' this is similar to '--option='=value'
[samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
39 #include "trans2.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
42 #include "util_tdb.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/util/util_file.h"
52 #include "lib/param/param.h"
53 #include "auth/gensec/gensec.h"
54 #include "lib/util/string_wrappers.h"
55 #include "source3/lib/substitute.h"
56
57 #include <gnutls/gnutls.h>
58 #include <gnutls/crypto.h>
59
60 extern char *optarg;
61 extern int optind;
62
63 fstring host, workgroup, share, password, username, myname;
64 struct cli_credentials *torture_creds;
65 static const char *sockops="TCP_NODELAY";
66 int torture_nprocs=1;
67 static int port_to_use=0;
68 int torture_numops=100;
69 int torture_blocksize=1024*1024;
70 static int procnum; /* records process count number when forking */
71 static struct cli_state *current_cli;
72 static fstring randomfname;
73 static bool use_oplocks;
74 static bool use_level_II_oplocks;
75 static const char *client_txt = "client_oplocks.txt";
76 static bool disable_spnego;
77 static bool use_kerberos;
78 static bool force_dos_errors;
79 static fstring multishare_conn_fname;
80 static bool use_multishare_conn = False;
81 static bool do_encrypt;
82 static const char *local_path = NULL;
83 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
84 char *test_filename;
85
86 bool torture_showall = False;
87
88 static double create_procs(bool (*fn)(int), bool *result);
89
90 /********************************************************************
91  Ensure a connection is encrypted.
92 ********************************************************************/
93
94 static bool force_cli_encryption(struct cli_state *c,
95                         const char *sharename)
96 {
97         uint16_t major, minor;
98         uint32_t caplow, caphigh;
99         NTSTATUS status;
100
101         if (!SERVER_HAS_UNIX_CIFS(c)) {
102                 d_printf("Encryption required and "
103                         "server that doesn't support "
104                         "UNIX extensions - failing connect\n");
105                         return false;
106         }
107
108         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
109                                              &caphigh);
110         if (!NT_STATUS_IS_OK(status)) {
111                 d_printf("Encryption required and "
112                         "can't get UNIX CIFS extensions "
113                         "version from server: %s\n", nt_errstr(status));
114                 return false;
115         }
116
117         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
118                 d_printf("Encryption required and "
119                         "share %s doesn't support "
120                         "encryption.\n", sharename);
121                 return false;
122         }
123
124         status = cli_smb1_setup_encryption(c, torture_creds);
125         if (!NT_STATUS_IS_OK(status)) {
126                 d_printf("Encryption required and "
127                         "setup failed with error %s.\n",
128                         nt_errstr(status));
129                 return false;
130         }
131
132         return true;
133 }
134
135
136 static struct cli_state *open_nbt_connection(void)
137 {
138         struct cli_state *c;
139         NTSTATUS status;
140         int flags = 0;
141
142         if (disable_spnego) {
143                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
144         }
145
146         if (use_oplocks) {
147                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
148         }
149
150         if (use_level_II_oplocks) {
151                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
152         }
153
154         if (force_dos_errors) {
155                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
156         }
157
158         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
159                                 signing_state, flags, &c);
160         if (!NT_STATUS_IS_OK(status)) {
161                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
162                 return NULL;
163         }
164
165         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
166
167         return c;
168 }
169
170 /****************************************************************************
171  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
172 ****************************************************************************/
173
174 static bool cli_bad_session_request(int fd,
175                          struct nmb_name *calling, struct nmb_name *called)
176 {
177         TALLOC_CTX *frame;
178         uint8_t len_buf[4];
179         struct iovec iov[3];
180         ssize_t len;
181         uint8_t *inbuf;
182         int err;
183         bool ret = false;
184         uint8_t message_type;
185         uint8_t error;
186         struct tevent_context *ev;
187         struct tevent_req *req;
188
189         frame = talloc_stackframe();
190
191         iov[0].iov_base = len_buf;
192         iov[0].iov_len  = sizeof(len_buf);
193
194         /* put in the destination name */
195
196         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
197                                       called->name_type);
198         if (iov[1].iov_base == NULL) {
199                 goto fail;
200         }
201         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
202                                   talloc_get_size(iov[1].iov_base));
203
204         /* and my name */
205
206         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
207                                       calling->name_type);
208         if (iov[2].iov_base == NULL) {
209                 goto fail;
210         }
211         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
212                                   talloc_get_size(iov[2].iov_base));
213
214         /* Deliberately corrupt the name len (first byte) */
215         *((uint8_t *)iov[2].iov_base) = 100;
216
217         /* send a session request (RFC 1002) */
218         /* setup the packet length
219          * Remove four bytes from the length count, since the length
220          * field in the NBT Session Service header counts the number
221          * of bytes which follow.  The cli_send_smb() function knows
222          * about this and accounts for those four bytes.
223          * CRH.
224          */
225
226         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
227         SCVAL(len_buf,0,0x81);
228
229         len = write_data_iov(fd, iov, 3);
230         if (len == -1) {
231                 goto fail;
232         }
233
234         ev = samba_tevent_context_init(frame);
235         if (ev == NULL) {
236                 goto fail;
237         }
238         req = read_smb_send(frame, ev, fd);
239         if (req == NULL) {
240                 goto fail;
241         }
242         if (!tevent_req_poll(req, ev)) {
243                 goto fail;
244         }
245         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
246         if (len == -1) {
247                 errno = err;
248                 goto fail;
249         }
250         TALLOC_FREE(ev);
251
252         message_type = CVAL(inbuf, 0);
253         if (message_type != 0x83) {
254                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
255                           message_type);
256                 goto fail;
257         }
258
259         if (smb_len(inbuf) != 1) {
260                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
261                           (int)smb_len(inbuf));
262                 goto fail;
263         }
264
265         error = CVAL(inbuf, 4);
266         if (error !=  0x82) {
267                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
268                           (int)error);
269                 goto fail;
270         }
271
272         ret = true;
273 fail:
274         TALLOC_FREE(frame);
275         return ret;
276 }
277
278 /* Insert a NULL at the first separator of the given path and return a pointer
279  * to the remainder of the string.
280  */
281 static char *
282 terminate_path_at_separator(char * path)
283 {
284         char * p;
285
286         if (!path) {
287                 return NULL;
288         }
289
290         if ((p = strchr_m(path, '/'))) {
291                 *p = '\0';
292                 return p + 1;
293         }
294
295         if ((p = strchr_m(path, '\\'))) {
296                 *p = '\0';
297                 return p + 1;
298         }
299
300         /* No separator. */
301         return NULL;
302 }
303
304 /*
305   parse a //server/share type UNC name
306 */
307 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
308                       char **hostname, char **sharename)
309 {
310         char *p;
311
312         *hostname = *sharename = NULL;
313
314         if (strncmp(unc_name, "\\\\", 2) &&
315             strncmp(unc_name, "//", 2)) {
316                 return False;
317         }
318
319         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
320         p = terminate_path_at_separator(*hostname);
321
322         if (p && *p) {
323                 *sharename = talloc_strdup(mem_ctx, p);
324                 terminate_path_at_separator(*sharename);
325         }
326
327         if (*hostname && *sharename) {
328                 return True;
329         }
330
331         TALLOC_FREE(*hostname);
332         TALLOC_FREE(*sharename);
333         return False;
334 }
335
336 static bool torture_open_connection_share(struct cli_state **c,
337                                    const char *hostname, 
338                                    const char *sharename,
339                                    int flags)
340 {
341         NTSTATUS status;
342
343         status = cli_full_connection_creds(c,
344                                            myname,
345                                            hostname,
346                                            NULL, /* dest_ss */
347                                            port_to_use,
348                                            sharename,
349                                            "?????",
350                                            torture_creds,
351                                            flags);
352         if (!NT_STATUS_IS_OK(status)) {
353                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
354                         hostname, sharename, port_to_use, nt_errstr(status));
355                 return False;
356         }
357
358         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
359
360         if (do_encrypt) {
361                 return force_cli_encryption(*c,
362                                         sharename);
363         }
364         return True;
365 }
366
367 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
368 {
369         char **unc_list = NULL;
370         int num_unc_names = 0;
371         bool result;
372
373         if (use_multishare_conn==True) {
374                 char *h, *s;
375                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
376                 if (!unc_list || num_unc_names <= 0) {
377                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
378                         exit(1);
379                 }
380
381                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382                                       NULL, &h, &s)) {
383                         printf("Failed to parse UNC name %s\n",
384                                unc_list[conn_index % num_unc_names]);
385                         TALLOC_FREE(unc_list);
386                         exit(1);
387                 }
388
389                 result = torture_open_connection_share(c, h, s, flags);
390
391                 /* h, s were copied earlier */
392                 TALLOC_FREE(unc_list);
393                 return result;
394         }
395
396         return torture_open_connection_share(c, host, share, flags);
397 }
398
399 bool torture_open_connection(struct cli_state **c, int conn_index)
400 {
401         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
402
403         if (use_oplocks) {
404                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
405         }
406         if (use_level_II_oplocks) {
407                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
408         }
409
410         return torture_open_connection_flags(c, conn_index, flags);
411 }
412
413 bool torture_init_connection(struct cli_state **pcli)
414 {
415         struct cli_state *cli;
416
417         cli = open_nbt_connection();
418         if (cli == NULL) {
419                 return false;
420         }
421
422         *pcli = cli;
423         return true;
424 }
425
426 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
427 {
428         uint16_t old_vuid = cli_state_get_uid(cli);
429         NTSTATUS status;
430         bool ret;
431
432         cli_state_set_uid(cli, 0);
433         status = cli_session_setup_creds(cli, torture_creds);
434         ret = NT_STATUS_IS_OK(status);
435         *new_vuid = cli_state_get_uid(cli);
436         cli_state_set_uid(cli, old_vuid);
437         return ret;
438 }
439
440
441 bool torture_close_connection(struct cli_state *c)
442 {
443         bool ret = True;
444         NTSTATUS status;
445
446         status = cli_tdis(c);
447         if (!NT_STATUS_IS_OK(status)) {
448                 printf("tdis failed (%s)\n", nt_errstr(status));
449                 ret = False;
450         }
451
452         cli_shutdown(c);
453
454         return ret;
455 }
456
457 void torture_conn_set_sockopt(struct cli_state *cli)
458 {
459         smbXcli_conn_set_sockopt(cli->conn, sockops);
460 }
461
462 static NTSTATUS torture_delete_fn(struct file_info *finfo,
463                                   const char *pattern,
464                                   void *state)
465 {
466         NTSTATUS status;
467         char *filename = NULL;
468         char *dirname = NULL;
469         char *p = NULL;
470         TALLOC_CTX *frame = talloc_stackframe();
471         struct cli_state *cli = (struct cli_state *)state;
472
473         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
474                 TALLOC_FREE(frame);
475                 return NT_STATUS_OK;
476         }
477
478         dirname = talloc_strdup(frame, pattern);
479         if (dirname == NULL) {
480                 TALLOC_FREE(frame);
481                 return NT_STATUS_NO_MEMORY;
482         }
483         p = strrchr_m(dirname, '\\');
484         if (p != NULL) {
485                 /* Remove the terminating '\' */
486                 *p = '\0';
487         }
488         if (dirname[0] != '\0') {
489                 filename = talloc_asprintf(frame,
490                                            "%s\\%s",
491                                            dirname,
492                                            finfo->name);
493         } else {
494                 filename = talloc_asprintf(frame,
495                                            "%s",
496                                            finfo->name);
497         }
498         if (filename == NULL) {
499                 TALLOC_FREE(frame);
500                 return NT_STATUS_NO_MEMORY;
501         }
502         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
503                 char *subdirname = talloc_asprintf(frame,
504                                                    "%s\\*",
505                                                    filename);
506                 if (subdirname == NULL) {
507                         TALLOC_FREE(frame);
508                         return NT_STATUS_NO_MEMORY;
509                 }
510                 status = cli_list(cli,
511                                   subdirname,
512                                   FILE_ATTRIBUTE_DIRECTORY |
513                                           FILE_ATTRIBUTE_HIDDEN |
514                                           FILE_ATTRIBUTE_SYSTEM,
515                                   torture_delete_fn,
516                                   cli);
517                 if (!NT_STATUS_IS_OK(status)) {
518                         printf("torture_delete_fn: cli_list "
519                                 "of %s failed (%s)\n",
520                                 subdirname,
521                                 nt_errstr(status));
522                         TALLOC_FREE(frame);
523                         return status;
524                 }
525                 status = cli_rmdir(cli, filename);
526         } else {
527                 status = cli_unlink(cli,
528                                     filename,
529                                     FILE_ATTRIBUTE_SYSTEM |
530                                         FILE_ATTRIBUTE_HIDDEN);
531         }
532         if (!NT_STATUS_IS_OK(status)) {
533                 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
534                         printf("torture_delete_fn: cli_rmdir"
535                                 " of %s failed (%s)\n",
536                                 filename,
537                                 nt_errstr(status));
538                 } else {
539                         printf("torture_delete_fn: cli_unlink"
540                                 " of %s failed (%s)\n",
541                                 filename,
542                                 nt_errstr(status));
543                 }
544         }
545         TALLOC_FREE(frame);
546         return status;
547 }
548
549 void torture_deltree(struct cli_state *cli, const char *dname)
550 {
551         char *mask = NULL;
552         NTSTATUS status;
553
554         /* It might be a file */
555         (void)cli_unlink(cli,
556                          dname,
557                          FILE_ATTRIBUTE_SYSTEM |
558                                 FILE_ATTRIBUTE_HIDDEN);
559
560         mask = talloc_asprintf(cli,
561                                "%s\\*",
562                                dname);
563         if (mask == NULL) {
564                 printf("torture_deltree: talloc_asprintf failed\n");
565                 return;
566         }
567
568         status = cli_list(cli,
569                         mask,
570                         FILE_ATTRIBUTE_DIRECTORY |
571                                 FILE_ATTRIBUTE_HIDDEN|
572                                 FILE_ATTRIBUTE_SYSTEM,
573                         torture_delete_fn,
574                         cli);
575         if (!NT_STATUS_IS_OK(status)) {
576                 printf("torture_deltree: cli_list of %s failed (%s)\n",
577                         mask,
578                         nt_errstr(status));
579         }
580         TALLOC_FREE(mask);
581         status = cli_rmdir(cli, dname);
582         if (!NT_STATUS_IS_OK(status)) {
583                 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
584                         dname,
585                         nt_errstr(status));
586         }
587 }
588
589 /* check if the server produced the expected dos or nt error code */
590 static bool check_both_error(int line, NTSTATUS status,
591                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
592 {
593         if (NT_STATUS_IS_DOS(status)) {
594                 uint8_t cclass;
595                 uint32_t num;
596
597                 /* Check DOS error */
598                 cclass = NT_STATUS_DOS_CLASS(status);
599                 num = NT_STATUS_DOS_CODE(status);
600
601                 if (eclass != cclass || ecode != num) {
602                         printf("unexpected error code class=%d code=%d\n",
603                                (int)cclass, (int)num);
604                         printf(" expected %d/%d %s (line=%d)\n",
605                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
606                         return false;
607                 }
608         } else {
609                 /* Check NT error */
610                 if (!NT_STATUS_EQUAL(nterr, status)) {
611                         printf("unexpected error code %s\n",
612                                 nt_errstr(status));
613                         printf(" expected %s (line=%d)\n",
614                                 nt_errstr(nterr), line);
615                         return false;
616                 }
617         }
618
619         return true;
620 }
621
622
623 /* check if the server produced the expected error code */
624 static bool check_error(int line, NTSTATUS status,
625                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
626 {
627         if (NT_STATUS_IS_DOS(status)) {
628                 uint8_t cclass;
629                 uint32_t num;
630
631                 /* Check DOS error */
632
633                 cclass = NT_STATUS_DOS_CLASS(status);
634                 num = NT_STATUS_DOS_CODE(status);
635
636                 if (eclass != cclass || ecode != num) {
637                         printf("unexpected error code class=%d code=%d\n", 
638                                (int)cclass, (int)num);
639                         printf(" expected %d/%d %s (line=%d)\n", 
640                                (int)eclass, (int)ecode, nt_errstr(nterr),
641                                line);
642                         return False;
643                 }
644
645         } else {
646                 /* Check NT error */
647
648                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
649                         printf("unexpected error code %s\n",
650                                nt_errstr(status));
651                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
652                                line);
653                         return False;
654                 }
655         }
656
657         return True;
658 }
659
660 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
661                         const char *fname,
662                         time_t *change_time,
663                         time_t *access_time,
664                         time_t *write_time,
665                         off_t *size,
666                         uint32_t *pattr)
667 {
668         int timezone = smb1cli_conn_server_time_zone(cli->conn);
669         time_t (*date_fn)(const void *buf, int serverzone) = NULL;
670         uint8_t *rdata = NULL;
671         uint32_t num_rdata;
672         NTSTATUS status;
673
674         status = cli_qpathinfo(talloc_tos(),
675                                cli,
676                                fname,
677                                SMB_INFO_STANDARD,
678                                22,
679                                CLI_BUFFER_SIZE,
680                                &rdata,
681                                &num_rdata);
682         if (!NT_STATUS_IS_OK(status)) {
683                 return status;
684         }
685         if (cli->win95) {
686                 date_fn = make_unix_date;
687         } else {
688                 date_fn = make_unix_date2;
689         }
690
691         if (change_time) {
692                 *change_time = date_fn(rdata + 0, timezone);
693         }
694         if (access_time) {
695                 *access_time = date_fn(rdata + 4, timezone);
696         }
697         if (write_time) {
698                 *write_time = date_fn(rdata + 8, timezone);
699         }
700         if (size) {
701                 *size = PULL_LE_U32(rdata, 12);
702         }
703         if (pattr) {
704                 *pattr = PULL_LE_U16(rdata, l1_attrFile);
705         }
706         return NT_STATUS_OK;
707 }
708
709 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
710 {
711         NTSTATUS status;
712
713         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
714
715         while (!NT_STATUS_IS_OK(status)) {
716                 if (!check_both_error(__LINE__, status, ERRDOS,
717                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
718                         return false;
719                 }
720
721                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
722         }
723
724         return true;
725 }
726
727
728 static bool rw_torture(struct cli_state *c)
729 {
730         const char *lockfname = "\\torture.lck";
731         fstring fname;
732         uint16_t fnum;
733         uint16_t fnum2;
734         pid_t pid2, pid = getpid();
735         int i, j;
736         char buf[1024];
737         bool correct = True;
738         size_t nread = 0;
739         NTSTATUS status;
740
741         memset(buf, '\0', sizeof(buf));
742
743         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
744                          DENY_NONE, &fnum2);
745         if (!NT_STATUS_IS_OK(status)) {
746                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
747         }
748         if (!NT_STATUS_IS_OK(status)) {
749                 printf("open of %s failed (%s)\n",
750                        lockfname, nt_errstr(status));
751                 return False;
752         }
753
754         for (i=0;i<torture_numops;i++) {
755                 unsigned n = (unsigned)sys_random()%10;
756
757                 if (i % 10 == 0) {
758                         printf("%d\r", i); fflush(stdout);
759                 }
760                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
761
762                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
763                         return False;
764                 }
765
766                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
767                                   DENY_ALL, &fnum);
768                 if (!NT_STATUS_IS_OK(status)) {
769                         printf("open failed (%s)\n", nt_errstr(status));
770                         correct = False;
771                         break;
772                 }
773
774                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
775                                       sizeof(pid), NULL);
776                 if (!NT_STATUS_IS_OK(status)) {
777                         printf("write failed (%s)\n", nt_errstr(status));
778                         correct = False;
779                 }
780
781                 for (j=0;j<50;j++) {
782                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
783                                               sizeof(pid)+(j*sizeof(buf)),
784                                               sizeof(buf), NULL);
785                         if (!NT_STATUS_IS_OK(status)) {
786                                 printf("write failed (%s)\n",
787                                        nt_errstr(status));
788                                 correct = False;
789                         }
790                 }
791
792                 pid2 = 0;
793
794                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
795                                   &nread);
796                 if (!NT_STATUS_IS_OK(status)) {
797                         printf("read failed (%s)\n", nt_errstr(status));
798                         correct = false;
799                 } else if (nread != sizeof(pid)) {
800                         printf("read/write compare failed: "
801                                "recv %ld req %ld\n", (unsigned long)nread,
802                                (unsigned long)sizeof(pid));
803                         correct = false;
804                 }
805
806                 if (pid2 != pid) {
807                         printf("data corruption!\n");
808                         correct = False;
809                 }
810
811                 status = cli_close(c, fnum);
812                 if (!NT_STATUS_IS_OK(status)) {
813                         printf("close failed (%s)\n", nt_errstr(status));
814                         correct = False;
815                 }
816
817                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
818                 if (!NT_STATUS_IS_OK(status)) {
819                         printf("unlink failed (%s)\n", nt_errstr(status));
820                         correct = False;
821                 }
822
823                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
824                 if (!NT_STATUS_IS_OK(status)) {
825                         printf("unlock failed (%s)\n", nt_errstr(status));
826                         correct = False;
827                 }
828         }
829
830         cli_close(c, fnum2);
831         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
832
833         printf("%d\n", i);
834
835         return correct;
836 }
837
838 static bool run_torture(int dummy)
839 {
840         struct cli_state *cli;
841         bool ret;
842
843         cli = current_cli;
844
845         smbXcli_conn_set_sockopt(cli->conn, sockops);
846
847         ret = rw_torture(cli);
848
849         if (!torture_close_connection(cli)) {
850                 ret = False;
851         }
852
853         return ret;
854 }
855
856 static bool rw_torture3(struct cli_state *c, char *lockfname)
857 {
858         uint16_t fnum = (uint16_t)-1;
859         unsigned int i = 0;
860         char buf[131072];
861         char buf_rd[131072];
862         unsigned count;
863         unsigned countprev = 0;
864         size_t sent = 0;
865         bool correct = True;
866         NTSTATUS status = NT_STATUS_OK;
867
868         srandom(1);
869         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
870         {
871                 SIVAL(buf, i, sys_random());
872         }
873
874         if (procnum == 0)
875         {
876                 status = cli_unlink(
877                         c, lockfname,
878                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
879                 if (!NT_STATUS_IS_OK(status)) {
880                         printf("unlink failed (%s) (normal, this file should "
881                                "not exist)\n", nt_errstr(status));
882                 }
883
884                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
885                                   DENY_NONE, &fnum);
886                 if (!NT_STATUS_IS_OK(status)) {
887                         printf("first open read/write of %s failed (%s)\n",
888                                         lockfname, nt_errstr(status));
889                         return False;
890                 }
891         }
892         else
893         {
894                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
895                 {
896                         status = cli_openx(c, lockfname, O_RDONLY, 
897                                          DENY_NONE, &fnum);
898                         if (NT_STATUS_IS_OK(status)) {
899                                 break;
900                         }
901                         smb_msleep(10);
902                 }
903                 if (!NT_STATUS_IS_OK(status)) {
904                         printf("second open read-only of %s failed (%s)\n",
905                                         lockfname, nt_errstr(status));
906                         return False;
907                 }
908         }
909
910         i = 0;
911         for (count = 0; count < sizeof(buf); count += sent)
912         {
913                 if (count >= countprev) {
914                         printf("%d %8d\r", i, count);
915                         fflush(stdout);
916                         i++;
917                         countprev += (sizeof(buf) / 20);
918                 }
919
920                 if (procnum == 0)
921                 {
922                         sent = ((unsigned)sys_random()%(20))+ 1;
923                         if (sent > sizeof(buf) - count)
924                         {
925                                 sent = sizeof(buf) - count;
926                         }
927
928                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
929                                               count, sent, NULL);
930                         if (!NT_STATUS_IS_OK(status)) {
931                                 printf("write failed (%s)\n",
932                                        nt_errstr(status));
933                                 correct = False;
934                         }
935                 }
936                 else
937                 {
938                         status = cli_read(c, fnum, buf_rd+count, count,
939                                           sizeof(buf)-count, &sent);
940                         if(!NT_STATUS_IS_OK(status)) {
941                                 printf("read failed offset:%d size:%ld (%s)\n",
942                                        count, (unsigned long)sizeof(buf)-count,
943                                        nt_errstr(status));
944                                 correct = False;
945                                 sent = 0;
946                         } else if (sent > 0) {
947                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
948                                 {
949                                         printf("read/write compare failed\n");
950                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
951                                         correct = False;
952                                         break;
953                                 }
954                         }
955                 }
956
957         }
958
959         status = cli_close(c, fnum);
960         if (!NT_STATUS_IS_OK(status)) {
961                 printf("close failed (%s)\n", nt_errstr(status));
962                 correct = False;
963         }
964
965         return correct;
966 }
967
968 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
969 {
970         const char *lockfname = "\\torture2.lck";
971         uint16_t fnum1;
972         uint16_t fnum2;
973         int i;
974         char buf[131072];
975         char buf_rd[131072];
976         bool correct = True;
977         size_t bytes_read;
978         NTSTATUS status;
979
980         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
981         if (!NT_STATUS_IS_OK(status)) {
982                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
983         }
984
985         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
986                           DENY_NONE, &fnum1);
987         if (!NT_STATUS_IS_OK(status)) {
988                 printf("first open read/write of %s failed (%s)\n",
989                                 lockfname, nt_errstr(status));
990                 return False;
991         }
992
993         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
994         if (!NT_STATUS_IS_OK(status)) {
995                 printf("second open read-only of %s failed (%s)\n",
996                                 lockfname, nt_errstr(status));
997                 cli_close(c1, fnum1);
998                 return False;
999         }
1000
1001         for (i = 0; i < torture_numops; i++)
1002         {
1003                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1004                 if (i % 10 == 0) {
1005                         printf("%d\r", i); fflush(stdout);
1006                 }
1007
1008                 generate_random_buffer((unsigned char *)buf, buf_size);
1009
1010                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1011                                       buf_size, NULL);
1012                 if (!NT_STATUS_IS_OK(status)) {
1013                         printf("write failed (%s)\n", nt_errstr(status));
1014                         correct = False;
1015                         break;
1016                 }
1017
1018                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1019                 if(!NT_STATUS_IS_OK(status)) {
1020                         printf("read failed (%s)\n", nt_errstr(status));
1021                         correct = false;
1022                         break;
1023                 } else if (bytes_read != buf_size) {
1024                         printf("read failed\n");
1025                         printf("read %ld, expected %ld\n",
1026                                (unsigned long)bytes_read,
1027                                (unsigned long)buf_size); 
1028                         correct = False;
1029                         break;
1030                 }
1031
1032                 if (memcmp(buf_rd, buf, buf_size) != 0)
1033                 {
1034                         printf("read/write compare failed\n");
1035                         correct = False;
1036                         break;
1037                 }
1038         }
1039
1040         status = cli_close(c2, fnum2);
1041         if (!NT_STATUS_IS_OK(status)) {
1042                 printf("close failed (%s)\n", nt_errstr(status));
1043                 correct = False;
1044         }
1045
1046         status = cli_close(c1, fnum1);
1047         if (!NT_STATUS_IS_OK(status)) {
1048                 printf("close failed (%s)\n", nt_errstr(status));
1049                 correct = False;
1050         }
1051
1052         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1053         if (!NT_STATUS_IS_OK(status)) {
1054                 printf("unlink failed (%s)\n", nt_errstr(status));
1055                 correct = False;
1056         }
1057
1058         return correct;
1059 }
1060
1061 static bool run_readwritetest(int dummy)
1062 {
1063         struct cli_state *cli1, *cli2;
1064         bool test1, test2 = False;
1065
1066         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1067                 return False;
1068         }
1069         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1070         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1071
1072         printf("starting readwritetest\n");
1073
1074         test1 = rw_torture2(cli1, cli2);
1075         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1076
1077         if (test1) {
1078                 test2 = rw_torture2(cli1, cli1);
1079                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1080         }
1081
1082         if (!torture_close_connection(cli1)) {
1083                 test1 = False;
1084         }
1085
1086         if (!torture_close_connection(cli2)) {
1087                 test2 = False;
1088         }
1089
1090         return (test1 && test2);
1091 }
1092
1093 static bool run_readwritemulti(int dummy)
1094 {
1095         struct cli_state *cli;
1096         bool test;
1097
1098         cli = current_cli;
1099
1100         smbXcli_conn_set_sockopt(cli->conn, sockops);
1101
1102         printf("run_readwritemulti: fname %s\n", randomfname);
1103         test = rw_torture3(cli, randomfname);
1104
1105         if (!torture_close_connection(cli)) {
1106                 test = False;
1107         }
1108
1109         return test;
1110 }
1111
1112 static bool run_readwritelarge_internal(void)
1113 {
1114         static struct cli_state *cli1;
1115         uint16_t fnum1;
1116         const char *lockfname = "\\large.dat";
1117         off_t fsize;
1118         char buf[126*1024];
1119         bool correct = True;
1120         NTSTATUS status;
1121
1122         if (!torture_open_connection(&cli1, 0)) {
1123                 return False;
1124         }
1125         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1126         memset(buf,'\0',sizeof(buf));
1127
1128         printf("starting readwritelarge_internal\n");
1129
1130         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1131
1132         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1133                           DENY_NONE, &fnum1);
1134         if (!NT_STATUS_IS_OK(status)) {
1135                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1136                 return False;
1137         }
1138
1139         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1140
1141         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1142                                      NULL, NULL, NULL);
1143         if (!NT_STATUS_IS_OK(status)) {
1144                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1145                 correct = False;
1146         }
1147
1148         if (fsize == sizeof(buf))
1149                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1150                        (unsigned long)fsize);
1151         else {
1152                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1153                        (unsigned long)fsize);
1154                 correct = False;
1155         }
1156
1157         status = cli_close(cli1, fnum1);
1158         if (!NT_STATUS_IS_OK(status)) {
1159                 printf("close failed (%s)\n", nt_errstr(status));
1160                 correct = False;
1161         }
1162
1163         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1164         if (!NT_STATUS_IS_OK(status)) {
1165                 printf("unlink failed (%s)\n", nt_errstr(status));
1166                 correct = False;
1167         }
1168
1169         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1170                           DENY_NONE, &fnum1);
1171         if (!NT_STATUS_IS_OK(status)) {
1172                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1173                 return False;
1174         }
1175
1176         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1177
1178         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1179                                      NULL, NULL, NULL);
1180         if (!NT_STATUS_IS_OK(status)) {
1181                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1182                 correct = False;
1183         }
1184
1185         if (fsize == sizeof(buf))
1186                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1187                        (unsigned long)fsize);
1188         else {
1189                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1190                        (unsigned long)fsize);
1191                 correct = False;
1192         }
1193
1194         status = cli_close(cli1, fnum1);
1195         if (!NT_STATUS_IS_OK(status)) {
1196                 printf("close failed (%s)\n", nt_errstr(status));
1197                 correct = False;
1198         }
1199
1200         if (!torture_close_connection(cli1)) {
1201                 correct = False;
1202         }
1203         return correct;
1204 }
1205
1206 static bool run_readwritelarge(int dummy)
1207 {
1208         return run_readwritelarge_internal();
1209 }
1210
1211 static bool run_readwritelarge_signtest(int dummy)
1212 {
1213         bool ret;
1214         signing_state = SMB_SIGNING_REQUIRED;
1215         ret = run_readwritelarge_internal();
1216         signing_state = SMB_SIGNING_DEFAULT;
1217         return ret;
1218 }
1219
1220 int line_count = 0;
1221 int nbio_id;
1222
1223 #define ival(s) strtol(s, NULL, 0)
1224
1225 /* run a test that simulates an approximate netbench client load */
1226 static bool run_netbench(int client)
1227 {
1228         struct cli_state *cli;
1229         int i;
1230         char line[1024];
1231         char cname[20];
1232         FILE *f;
1233         const char *params[20];
1234         bool correct = True;
1235
1236         cli = current_cli;
1237
1238         nbio_id = client;
1239
1240         smbXcli_conn_set_sockopt(cli->conn, sockops);
1241
1242         nb_setup(cli);
1243
1244         slprintf(cname,sizeof(cname)-1, "client%d", client);
1245
1246         f = fopen(client_txt, "r");
1247
1248         if (!f) {
1249                 perror(client_txt);
1250                 return False;
1251         }
1252
1253         while (fgets(line, sizeof(line)-1, f)) {
1254                 char *saveptr;
1255                 line_count++;
1256
1257                 line[strlen(line)-1] = 0;
1258
1259                 /* printf("[%d] %s\n", line_count, line); */
1260
1261                 all_string_sub(line,"client1", cname, sizeof(line));
1262
1263                 /* parse the command parameters */
1264                 params[0] = strtok_r(line, " ", &saveptr);
1265                 i = 0;
1266                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1267
1268                 params[i] = "";
1269
1270                 if (i < 2) continue;
1271
1272                 if (!strncmp(params[0],"SMB", 3)) {
1273                         printf("ERROR: You are using a dbench 1 load file\n");
1274                         exit(1);
1275                 }
1276
1277                 if (!strcmp(params[0],"NTCreateX")) {
1278                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1279                                    ival(params[4]));
1280                 } else if (!strcmp(params[0],"Close")) {
1281                         nb_close(ival(params[1]));
1282                 } else if (!strcmp(params[0],"Rename")) {
1283                         nb_rename(params[1], params[2]);
1284                 } else if (!strcmp(params[0],"Unlink")) {
1285                         nb_unlink(params[1]);
1286                 } else if (!strcmp(params[0],"Deltree")) {
1287                         nb_deltree(params[1]);
1288                 } else if (!strcmp(params[0],"Rmdir")) {
1289                         nb_rmdir(params[1]);
1290                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1291                         nb_qpathinfo(params[1]);
1292                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1293                         nb_qfileinfo(ival(params[1]));
1294                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1295                         nb_qfsinfo(ival(params[1]));
1296                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1297                         nb_findfirst(params[1]);
1298                 } else if (!strcmp(params[0],"WriteX")) {
1299                         nb_writex(ival(params[1]), 
1300                                   ival(params[2]), ival(params[3]), ival(params[4]));
1301                 } else if (!strcmp(params[0],"ReadX")) {
1302                         nb_readx(ival(params[1]), 
1303                                   ival(params[2]), ival(params[3]), ival(params[4]));
1304                 } else if (!strcmp(params[0],"Flush")) {
1305                         nb_flush(ival(params[1]));
1306                 } else {
1307                         printf("Unknown operation %s\n", params[0]);
1308                         exit(1);
1309                 }
1310         }
1311         fclose(f);
1312
1313         nb_cleanup();
1314
1315         if (!torture_close_connection(cli)) {
1316                 correct = False;
1317         }
1318
1319         return correct;
1320 }
1321
1322
1323 /* run a test that simulates an approximate netbench client load */
1324 static bool run_nbench(int dummy)
1325 {
1326         double t;
1327         bool correct = True;
1328
1329         nbio_shmem(torture_nprocs);
1330
1331         nbio_id = -1;
1332
1333         signal(SIGALRM, nb_alarm);
1334         alarm(1);
1335         t = create_procs(run_netbench, &correct);
1336         alarm(0);
1337
1338         printf("\nThroughput %g MB/sec\n", 
1339                1.0e-6 * nbio_total() / t);
1340         return correct;
1341 }
1342
1343
1344 /*
1345   This test checks for two things:
1346
1347   1) correct support for retaining locks over a close (ie. the server
1348      must not use posix semantics)
1349   2) support for lock timeouts
1350  */
1351 static bool run_locktest1(int dummy)
1352 {
1353         struct cli_state *cli1, *cli2;
1354         const char *fname = "\\lockt1.lck";
1355         uint16_t fnum1, fnum2, fnum3;
1356         time_t t1, t2;
1357         unsigned lock_timeout;
1358         NTSTATUS status;
1359
1360         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1361                 return False;
1362         }
1363         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1364         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1365
1366         printf("starting locktest1\n");
1367
1368         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1369
1370         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1371                           &fnum1);
1372         if (!NT_STATUS_IS_OK(status)) {
1373                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1374                 return False;
1375         }
1376
1377         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1378         if (!NT_STATUS_IS_OK(status)) {
1379                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1380                 return False;
1381         }
1382
1383         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1384         if (!NT_STATUS_IS_OK(status)) {
1385                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1386                 return False;
1387         }
1388
1389         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1390         if (!NT_STATUS_IS_OK(status)) {
1391                 printf("lock1 failed (%s)\n", nt_errstr(status));
1392                 return false;
1393         }
1394
1395         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1396         if (NT_STATUS_IS_OK(status)) {
1397                 printf("lock2 succeeded! This is a locking bug\n");
1398                 return false;
1399         } else {
1400                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1401                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1402                         return false;
1403                 }
1404         }
1405
1406         lock_timeout = (1 + (random() % 20));
1407         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1408         t1 = time(NULL);
1409         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1410         if (NT_STATUS_IS_OK(status)) {
1411                 printf("lock3 succeeded! This is a locking bug\n");
1412                 return false;
1413         } else {
1414                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1415                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1416                         return false;
1417                 }
1418         }
1419         t2 = time(NULL);
1420
1421         if (ABS(t2 - t1) < lock_timeout-1) {
1422                 printf("error: This server appears not to support timed lock requests\n");
1423         }
1424
1425         printf("server slept for %u seconds for a %u second timeout\n",
1426                (unsigned int)(t2-t1), lock_timeout);
1427
1428         status = cli_close(cli1, fnum2);
1429         if (!NT_STATUS_IS_OK(status)) {
1430                 printf("close1 failed (%s)\n", nt_errstr(status));
1431                 return False;
1432         }
1433
1434         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1435         if (NT_STATUS_IS_OK(status)) {
1436                 printf("lock4 succeeded! This is a locking bug\n");
1437                 return false;
1438         } else {
1439                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1440                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1441                         return false;
1442                 }
1443         }
1444
1445         status = cli_close(cli1, fnum1);
1446         if (!NT_STATUS_IS_OK(status)) {
1447                 printf("close2 failed (%s)\n", nt_errstr(status));
1448                 return False;
1449         }
1450
1451         status = cli_close(cli2, fnum3);
1452         if (!NT_STATUS_IS_OK(status)) {
1453                 printf("close3 failed (%s)\n", nt_errstr(status));
1454                 return False;
1455         }
1456
1457         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1458         if (!NT_STATUS_IS_OK(status)) {
1459                 printf("unlink failed (%s)\n", nt_errstr(status));
1460                 return False;
1461         }
1462
1463
1464         if (!torture_close_connection(cli1)) {
1465                 return False;
1466         }
1467
1468         if (!torture_close_connection(cli2)) {
1469                 return False;
1470         }
1471
1472         printf("Passed locktest1\n");
1473         return True;
1474 }
1475
1476 /*
1477   this checks to see if a secondary tconx can use open files from an
1478   earlier tconx
1479  */
1480 static bool run_tcon_test(int dummy)
1481 {
1482         static struct cli_state *cli;
1483         const char *fname = "\\tcontest.tmp";
1484         uint16_t fnum1;
1485         uint32_t cnum1, cnum2, cnum3;
1486         struct smbXcli_tcon *orig_tcon = NULL;
1487         char *orig_share = NULL;
1488         uint16_t vuid1, vuid2;
1489         char buf[4];
1490         bool ret = True;
1491         NTSTATUS status;
1492
1493         memset(buf, '\0', sizeof(buf));
1494
1495         if (!torture_open_connection(&cli, 0)) {
1496                 return False;
1497         }
1498         smbXcli_conn_set_sockopt(cli->conn, sockops);
1499
1500         printf("starting tcontest\n");
1501
1502         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1503
1504         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1505         if (!NT_STATUS_IS_OK(status)) {
1506                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1507                 return False;
1508         }
1509
1510         cnum1 = cli_state_get_tid(cli);
1511         vuid1 = cli_state_get_uid(cli);
1512
1513         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1514         if (!NT_STATUS_IS_OK(status)) {
1515                 printf("initial write failed (%s)", nt_errstr(status));
1516                 return False;
1517         }
1518
1519         cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1520
1521         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1522         if (!NT_STATUS_IS_OK(status)) {
1523                 printf("%s refused 2nd tree connect (%s)\n", host,
1524                        nt_errstr(status));
1525                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1526                 cli_shutdown(cli);
1527                 return False;
1528         }
1529
1530         cnum2 = cli_state_get_tid(cli);
1531         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1532         vuid2 = cli_state_get_uid(cli) + 1;
1533
1534         /* try a write with the wrong tid */
1535         cli_state_set_tid(cli, cnum2);
1536
1537         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1538         if (NT_STATUS_IS_OK(status)) {
1539                 printf("* server allows write with wrong TID\n");
1540                 ret = False;
1541         } else {
1542                 printf("server fails write with wrong TID : %s\n",
1543                        nt_errstr(status));
1544         }
1545
1546
1547         /* try a write with an invalid tid */
1548         cli_state_set_tid(cli, cnum3);
1549
1550         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1551         if (NT_STATUS_IS_OK(status)) {
1552                 printf("* server allows write with invalid TID\n");
1553                 ret = False;
1554         } else {
1555                 printf("server fails write with invalid TID : %s\n",
1556                        nt_errstr(status));
1557         }
1558
1559         /* try a write with an invalid vuid */
1560         cli_state_set_uid(cli, vuid2);
1561         cli_state_set_tid(cli, cnum1);
1562
1563         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1564         if (NT_STATUS_IS_OK(status)) {
1565                 printf("* server allows write with invalid VUID\n");
1566                 ret = False;
1567         } else {
1568                 printf("server fails write with invalid VUID : %s\n",
1569                        nt_errstr(status));
1570         }
1571
1572         cli_state_set_tid(cli, cnum1);
1573         cli_state_set_uid(cli, vuid1);
1574
1575         status = cli_close(cli, fnum1);
1576         if (!NT_STATUS_IS_OK(status)) {
1577                 printf("close failed (%s)\n", nt_errstr(status));
1578                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1579                 cli_shutdown(cli);
1580                 return False;
1581         }
1582
1583         cli_state_set_tid(cli, cnum2);
1584
1585         status = cli_tdis(cli);
1586         if (!NT_STATUS_IS_OK(status)) {
1587                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1588                 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1589                 cli_shutdown(cli);
1590                 return False;
1591         }
1592
1593         cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1594
1595         cli_state_set_tid(cli, cnum1);
1596
1597         if (!torture_close_connection(cli)) {
1598                 return False;
1599         }
1600
1601         return ret;
1602 }
1603
1604
1605 /*
1606  checks for old style tcon support
1607  */
1608 static bool run_tcon2_test(int dummy)
1609 {
1610         static struct cli_state *cli;
1611         uint16_t cnum, max_xmit;
1612         char *service;
1613         NTSTATUS status;
1614
1615         if (!torture_open_connection(&cli, 0)) {
1616                 return False;
1617         }
1618         smbXcli_conn_set_sockopt(cli->conn, sockops);
1619
1620         printf("starting tcon2 test\n");
1621
1622         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1623                 return false;
1624         }
1625
1626         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1627
1628         SAFE_FREE(service);
1629
1630         if (!NT_STATUS_IS_OK(status)) {
1631                 printf("tcon2 failed : %s\n", nt_errstr(status));
1632         } else {
1633                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1634                        (int)max_xmit, (int)cnum);
1635         }
1636
1637         if (!torture_close_connection(cli)) {
1638                 return False;
1639         }
1640
1641         printf("Passed tcon2 test\n");
1642         return True;
1643 }
1644
1645 static bool tcon_devtest(struct cli_state *cli,
1646                          const char *myshare, const char *devtype,
1647                          const char *return_devtype,
1648                          NTSTATUS expected_error)
1649 {
1650         NTSTATUS status;
1651         bool ret;
1652
1653         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1654
1655         if (NT_STATUS_IS_OK(expected_error)) {
1656                 if (NT_STATUS_IS_OK(status)) {
1657                         if (return_devtype != NULL &&
1658                             strequal(cli->dev, return_devtype)) {
1659                                 ret = True;
1660                         } else { 
1661                                 printf("tconX to share %s with type %s "
1662                                        "succeeded but returned the wrong "
1663                                        "device type (got [%s] but should have got [%s])\n",
1664                                        myshare, devtype, cli->dev, return_devtype);
1665                                 ret = False;
1666                         }
1667                 } else {
1668                         printf("tconX to share %s with type %s "
1669                                "should have succeeded but failed\n",
1670                                myshare, devtype);
1671                         ret = False;
1672                 }
1673                 cli_tdis(cli);
1674         } else {
1675                 if (NT_STATUS_IS_OK(status)) {
1676                         printf("tconx to share %s with type %s "
1677                                "should have failed but succeeded\n",
1678                                myshare, devtype);
1679                         ret = False;
1680                 } else {
1681                         if (NT_STATUS_EQUAL(status, expected_error)) {
1682                                 ret = True;
1683                         } else {
1684                                 printf("Returned unexpected error\n");
1685                                 ret = False;
1686                         }
1687                 }
1688         }
1689         return ret;
1690 }
1691
1692 /*
1693  checks for correct tconX support
1694  */
1695 static bool run_tcon_devtype_test(int dummy)
1696 {
1697         static struct cli_state *cli1 = NULL;
1698         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1699         NTSTATUS status;
1700         bool ret = True;
1701
1702         status = cli_full_connection_creds(&cli1,
1703                                            myname,
1704                                            host,
1705                                            NULL, /* dest_ss */
1706                                            port_to_use,
1707                                            NULL, /* service */
1708                                            NULL, /* service_type */
1709                                            torture_creds,
1710                                            flags);
1711
1712         if (!NT_STATUS_IS_OK(status)) {
1713                 printf("could not open connection\n");
1714                 return False;
1715         }
1716
1717         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1718                 ret = False;
1719
1720         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1721                 ret = False;
1722
1723         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1724                 ret = False;
1725
1726         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1727                 ret = False;
1728
1729         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1730                 ret = False;
1731
1732         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1733                 ret = False;
1734
1735         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1736                 ret = False;
1737
1738         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1739                 ret = False;
1740
1741         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1742                 ret = False;
1743
1744         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1745                 ret = False;
1746
1747         cli_shutdown(cli1);
1748
1749         if (ret)
1750                 printf("Passed tcondevtest\n");
1751
1752         return ret;
1753 }
1754
1755
1756 /*
1757   This test checks that 
1758
1759   1) the server supports multiple locking contexts on the one SMB
1760   connection, distinguished by PID.  
1761
1762   2) the server correctly fails overlapping locks made by the same PID (this
1763      goes against POSIX behaviour, which is why it is tricky to implement)
1764
1765   3) the server denies unlock requests by an incorrect client PID
1766 */
1767 static bool run_locktest2(int dummy)
1768 {
1769         static struct cli_state *cli;
1770         const char *fname = "\\lockt2.lck";
1771         uint16_t fnum1, fnum2, fnum3;
1772         bool correct = True;
1773         NTSTATUS status;
1774
1775         if (!torture_open_connection(&cli, 0)) {
1776                 return False;
1777         }
1778
1779         smbXcli_conn_set_sockopt(cli->conn, sockops);
1780
1781         printf("starting locktest2\n");
1782
1783         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1784
1785         cli_setpid(cli, 1);
1786
1787         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1790                 return False;
1791         }
1792
1793         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1794         if (!NT_STATUS_IS_OK(status)) {
1795                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1796                 return False;
1797         }
1798
1799         cli_setpid(cli, 2);
1800
1801         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1802         if (!NT_STATUS_IS_OK(status)) {
1803                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1804                 return False;
1805         }
1806
1807         cli_setpid(cli, 1);
1808
1809         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1810         if (!NT_STATUS_IS_OK(status)) {
1811                 printf("lock1 failed (%s)\n", nt_errstr(status));
1812                 return false;
1813         }
1814
1815         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1816         if (NT_STATUS_IS_OK(status)) {
1817                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1818                 correct = false;
1819         } else {
1820                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1821                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1822                         return false;
1823                 }
1824         }
1825
1826         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1827         if (NT_STATUS_IS_OK(status)) {
1828                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1829                 correct = false;
1830         } else {
1831                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1832                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1833                         return false;
1834                 }
1835         }
1836
1837         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1838         if (NT_STATUS_IS_OK(status)) {
1839                 printf("READ lock2 succeeded! This is a locking bug\n");
1840                 correct = false;
1841         } else {
1842                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1843                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1844                         return false;
1845                 }
1846         }
1847
1848         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1849         if (!NT_STATUS_IS_OK(status)) {
1850                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1851         }
1852         cli_setpid(cli, 2);
1853         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1854                 printf("unlock at 100 succeeded! This is a locking bug\n");
1855                 correct = False;
1856         }
1857
1858         status = cli_unlock(cli, fnum1, 0, 4);
1859         if (NT_STATUS_IS_OK(status)) {
1860                 printf("unlock1 succeeded! This is a locking bug\n");
1861                 correct = false;
1862         } else {
1863                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1864                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1865                         return false;
1866                 }
1867         }
1868
1869         status = cli_unlock(cli, fnum1, 0, 8);
1870         if (NT_STATUS_IS_OK(status)) {
1871                 printf("unlock2 succeeded! This is a locking bug\n");
1872                 correct = false;
1873         } else {
1874                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1875                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1876                         return false;
1877                 }
1878         }
1879
1880         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1881         if (NT_STATUS_IS_OK(status)) {
1882                 printf("lock3 succeeded! This is a locking bug\n");
1883                 correct = false;
1884         } else {
1885                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1886                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1887                         return false;
1888                 }
1889         }
1890
1891         cli_setpid(cli, 1);
1892
1893         status = cli_close(cli, fnum1);
1894         if (!NT_STATUS_IS_OK(status)) {
1895                 printf("close1 failed (%s)\n", nt_errstr(status));
1896                 return False;
1897         }
1898
1899         status = cli_close(cli, fnum2);
1900         if (!NT_STATUS_IS_OK(status)) {
1901                 printf("close2 failed (%s)\n", nt_errstr(status));
1902                 return False;
1903         }
1904
1905         status = cli_close(cli, fnum3);
1906         if (!NT_STATUS_IS_OK(status)) {
1907                 printf("close3 failed (%s)\n", nt_errstr(status));
1908                 return False;
1909         }
1910
1911         if (!torture_close_connection(cli)) {
1912                 correct = False;
1913         }
1914
1915         printf("locktest2 finished\n");
1916
1917         return correct;
1918 }
1919
1920
1921 /*
1922   This test checks that 
1923
1924   1) the server supports the full offset range in lock requests
1925 */
1926 static bool run_locktest3(int dummy)
1927 {
1928         static struct cli_state *cli1, *cli2;
1929         const char *fname = "\\lockt3.lck";
1930         uint16_t fnum1, fnum2;
1931         int i;
1932         uint32_t offset;
1933         bool correct = True;
1934         NTSTATUS status;
1935
1936 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1937
1938         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1939                 return False;
1940         }
1941         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1942         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1943
1944         printf("starting locktest3\n");
1945
1946         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1947
1948         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1949                          &fnum1);
1950         if (!NT_STATUS_IS_OK(status)) {
1951                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1952                 return False;
1953         }
1954
1955         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1956         if (!NT_STATUS_IS_OK(status)) {
1957                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1958                 return False;
1959         }
1960
1961         for (offset=i=0;i<torture_numops;i++) {
1962                 NEXT_OFFSET;
1963
1964                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1965                 if (!NT_STATUS_IS_OK(status)) {
1966                         printf("lock1 %d failed (%s)\n", 
1967                                i,
1968                                nt_errstr(status));
1969                         return False;
1970                 }
1971
1972                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1973                 if (!NT_STATUS_IS_OK(status)) {
1974                         printf("lock2 %d failed (%s)\n", 
1975                                i,
1976                                nt_errstr(status));
1977                         return False;
1978                 }
1979         }
1980
1981         for (offset=i=0;i<torture_numops;i++) {
1982                 NEXT_OFFSET;
1983
1984                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1985                 if (NT_STATUS_IS_OK(status)) {
1986                         printf("error: lock1 %d succeeded!\n", i);
1987                         return False;
1988                 }
1989
1990                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1991                 if (NT_STATUS_IS_OK(status)) {
1992                         printf("error: lock2 %d succeeded!\n", i);
1993                         return False;
1994                 }
1995
1996                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1997                 if (NT_STATUS_IS_OK(status)) {
1998                         printf("error: lock3 %d succeeded!\n", i);
1999                         return False;
2000                 }
2001
2002                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2003                 if (NT_STATUS_IS_OK(status)) {
2004                         printf("error: lock4 %d succeeded!\n", i);
2005                         return False;
2006                 }
2007         }
2008
2009         for (offset=i=0;i<torture_numops;i++) {
2010                 NEXT_OFFSET;
2011
2012                 status = cli_unlock(cli1, fnum1, offset-1, 1);
2013                 if (!NT_STATUS_IS_OK(status)) {
2014                         printf("unlock1 %d failed (%s)\n", 
2015                                i,
2016                                nt_errstr(status));
2017                         return False;
2018                 }
2019
2020                 status = cli_unlock(cli2, fnum2, offset-2, 1);
2021                 if (!NT_STATUS_IS_OK(status)) {
2022                         printf("unlock2 %d failed (%s)\n", 
2023                                i,
2024                                nt_errstr(status));
2025                         return False;
2026                 }
2027         }
2028
2029         status = cli_close(cli1, fnum1);
2030         if (!NT_STATUS_IS_OK(status)) {
2031                 printf("close1 failed (%s)\n", nt_errstr(status));
2032                 return False;
2033         }
2034
2035         status = cli_close(cli2, fnum2);
2036         if (!NT_STATUS_IS_OK(status)) {
2037                 printf("close2 failed (%s)\n", nt_errstr(status));
2038                 return False;
2039         }
2040
2041         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2042         if (!NT_STATUS_IS_OK(status)) {
2043                 printf("unlink failed (%s)\n", nt_errstr(status));
2044                 return False;
2045         }
2046
2047         if (!torture_close_connection(cli1)) {
2048                 correct = False;
2049         }
2050
2051         if (!torture_close_connection(cli2)) {
2052                 correct = False;
2053         }
2054
2055         printf("finished locktest3\n");
2056
2057         return correct;
2058 }
2059
2060 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2061                            char *buf, off_t offset, size_t size,
2062                            size_t *nread, size_t expect)
2063 {
2064         NTSTATUS status;
2065         size_t l_nread;
2066
2067         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2068
2069         if(!NT_STATUS_IS_OK(status)) {
2070                 return false;
2071         } else if (l_nread != expect) {
2072                 return false;
2073         }
2074
2075         if (nread) {
2076                 *nread = l_nread;
2077         }
2078
2079         return true;
2080 }
2081
2082 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2083         printf("** "); correct = False; \
2084         }
2085
2086 /*
2087   looks at overlapping locks
2088 */
2089 static bool run_locktest4(int dummy)
2090 {
2091         static struct cli_state *cli1, *cli2;
2092         const char *fname = "\\lockt4.lck";
2093         uint16_t fnum1, fnum2, f;
2094         bool ret;
2095         char buf[1000];
2096         bool correct = True;
2097         NTSTATUS status;
2098
2099         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2100                 return False;
2101         }
2102
2103         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2104         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2105
2106         printf("starting locktest4\n");
2107
2108         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2109
2110         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2111         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2112
2113         memset(buf, 0, sizeof(buf));
2114
2115         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2116                               NULL);
2117         if (!NT_STATUS_IS_OK(status)) {
2118                 printf("Failed to create file: %s\n", nt_errstr(status));
2119                 correct = False;
2120                 goto fail;
2121         }
2122
2123         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2124               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2125         EXPECTED(ret, False);
2126         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2127
2128         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2129               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2130         EXPECTED(ret, True);
2131         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2132
2133         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2134               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2135         EXPECTED(ret, False);
2136         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2137
2138         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2139               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2140         EXPECTED(ret, True);
2141         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2142
2143         ret = (cli_setpid(cli1, 1),
2144               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2145               (cli_setpid(cli1, 2),
2146               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2147         EXPECTED(ret, False);
2148         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2149
2150         ret = (cli_setpid(cli1, 1),
2151               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2152               (cli_setpid(cli1, 2),
2153               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2154         EXPECTED(ret, True);
2155         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2156
2157         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2158               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2159         EXPECTED(ret, True);
2160         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2161
2162         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2163               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2164         EXPECTED(ret, False);
2165         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2166
2167         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2168               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2169         EXPECTED(ret, False);
2170         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2171
2172         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2173               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2174         EXPECTED(ret, True);
2175         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2176
2177         ret = (cli_setpid(cli1, 1),
2178              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2179              (cli_setpid(cli1, 2),
2180              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2181         EXPECTED(ret, False);
2182         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2183
2184         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2185               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2186               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2187         EXPECTED(ret, False);
2188         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2189
2190
2191         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2192               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2193         EXPECTED(ret, False);
2194         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2195
2196         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2197         ret = NT_STATUS_IS_OK(status);
2198         if (ret) {
2199                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2200                                       NULL);
2201                 ret = NT_STATUS_IS_OK(status);
2202         }
2203         EXPECTED(ret, False);
2204         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2205
2206
2207         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2208               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2209               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2210               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2211         EXPECTED(ret, True);
2212         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2213
2214
2215         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2216               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2217               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2218               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2219               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2220                                              150, 4, NULL))) &&
2221               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2222         EXPECTED(ret, True);
2223         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2224
2225         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2226               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2227               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2228                                            160, 4, NULL)) &&
2229               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2230         EXPECTED(ret, True);
2231         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2232
2233         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2234               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2235               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2236                                            170, 4, NULL)) &&
2237               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2238         EXPECTED(ret, True);
2239         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2240
2241         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2242               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2243               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2244               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2245                                             190, 4, NULL)) &&
2246               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2247         EXPECTED(ret, True);
2248         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2249
2250         cli_close(cli1, fnum1);
2251         cli_close(cli2, fnum2);
2252         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2253         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2254         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2255               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2256               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2257               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2258               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2259         cli_close(cli1, f);
2260         cli_close(cli1, fnum1);
2261         EXPECTED(ret, True);
2262         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2263
2264  fail:
2265         cli_close(cli1, fnum1);
2266         cli_close(cli2, fnum2);
2267         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2268         torture_close_connection(cli1);
2269         torture_close_connection(cli2);
2270
2271         printf("finished locktest4\n");
2272         return correct;
2273 }
2274
2275 /*
2276   looks at lock upgrade/downgrade.
2277 */
2278 static bool run_locktest5(int dummy)
2279 {
2280         static struct cli_state *cli1, *cli2;
2281         const char *fname = "\\lockt5.lck";
2282         uint16_t fnum1, fnum2, fnum3;
2283         bool ret;
2284         char buf[1000];
2285         bool correct = True;
2286         NTSTATUS status;
2287
2288         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2289                 return False;
2290         }
2291
2292         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2293         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2294
2295         printf("starting locktest5\n");
2296
2297         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2298
2299         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2300         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2301         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2302
2303         memset(buf, 0, sizeof(buf));
2304
2305         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2306                               NULL);
2307         if (!NT_STATUS_IS_OK(status)) {
2308                 printf("Failed to create file: %s\n", nt_errstr(status));
2309                 correct = False;
2310                 goto fail;
2311         }
2312
2313         /* Check for NT bug... */
2314         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2315               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2316         cli_close(cli1, fnum1);
2317         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2318         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2319         ret = NT_STATUS_IS_OK(status);
2320         EXPECTED(ret, True);
2321         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2322         cli_close(cli1, fnum1);
2323         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2324         cli_unlock(cli1, fnum3, 0, 1);
2325
2326         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2327               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2328         EXPECTED(ret, True);
2329         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2330
2331         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2332         ret = NT_STATUS_IS_OK(status);
2333         EXPECTED(ret, False);
2334
2335         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2336
2337         /* Unlock the process 2 lock. */
2338         cli_unlock(cli2, fnum2, 0, 4);
2339
2340         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2341         ret = NT_STATUS_IS_OK(status);
2342         EXPECTED(ret, False);
2343
2344         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2345
2346         /* Unlock the process 1 fnum3 lock. */
2347         cli_unlock(cli1, fnum3, 0, 4);
2348
2349         /* Stack 2 more locks here. */
2350         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2351               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2352
2353         EXPECTED(ret, True);
2354         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2355
2356         /* Unlock the first process lock, then check this was the WRITE lock that was
2357                 removed. */
2358
2359         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2360               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2361
2362         EXPECTED(ret, True);
2363         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2364
2365         /* Unlock the process 2 lock. */
2366         cli_unlock(cli2, fnum2, 0, 4);
2367
2368         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2369
2370         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2371                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2372                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2373
2374         EXPECTED(ret, True);
2375         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2376
2377         /* Ensure the next unlock fails. */
2378         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2379         EXPECTED(ret, False);
2380         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2381
2382         /* Ensure connection 2 can get a write lock. */
2383         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2384         ret = NT_STATUS_IS_OK(status);
2385         EXPECTED(ret, True);
2386
2387         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2388
2389
2390  fail:
2391         cli_close(cli1, fnum1);
2392         cli_close(cli2, fnum2);
2393         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2394         if (!torture_close_connection(cli1)) {
2395                 correct = False;
2396         }
2397         if (!torture_close_connection(cli2)) {
2398                 correct = False;
2399         }
2400
2401         printf("finished locktest5\n");
2402
2403         return correct;
2404 }
2405
2406 /*
2407   tries the unusual lockingX locktype bits
2408 */
2409 static bool run_locktest6(int dummy)
2410 {
2411         static struct cli_state *cli;
2412         const char *fname[1] = { "\\lock6.txt" };
2413         int i;
2414         uint16_t fnum;
2415         NTSTATUS status;
2416
2417         if (!torture_open_connection(&cli, 0)) {
2418                 return False;
2419         }
2420
2421         smbXcli_conn_set_sockopt(cli->conn, sockops);
2422
2423         printf("starting locktest6\n");
2424
2425         for (i=0;i<1;i++) {
2426                 printf("Testing %s\n", fname[i]);
2427
2428                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2429
2430                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2431                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2432                 cli_close(cli, fnum);
2433                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2434
2435                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2436                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2437                 cli_close(cli, fnum);
2438                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2439
2440                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2441         }
2442
2443         torture_close_connection(cli);
2444
2445         printf("finished locktest6\n");
2446         return True;
2447 }
2448
2449 static bool run_locktest7(int dummy)
2450 {
2451         struct cli_state *cli1;
2452         const char *fname = "\\lockt7.lck";
2453         uint16_t fnum1;
2454         char buf[200];
2455         bool correct = False;
2456         size_t nread;
2457         NTSTATUS status;
2458
2459         if (!torture_open_connection(&cli1, 0)) {
2460                 return False;
2461         }
2462
2463         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2464
2465         printf("starting locktest7\n");
2466
2467         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2468
2469         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2470
2471         memset(buf, 0, sizeof(buf));
2472
2473         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2474                               NULL);
2475         if (!NT_STATUS_IS_OK(status)) {
2476                 printf("Failed to create file: %s\n", nt_errstr(status));
2477                 goto fail;
2478         }
2479
2480         cli_setpid(cli1, 1);
2481
2482         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 printf("Unable to apply read lock on range 130:4, "
2485                        "error was %s\n", nt_errstr(status));
2486                 goto fail;
2487         } else {
2488                 printf("pid1 successfully locked range 130:4 for READ\n");
2489         }
2490
2491         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 printf("pid1 unable to read the range 130:4, error was %s\n",
2494                       nt_errstr(status));
2495                 goto fail;
2496         } else if (nread != 4) {
2497                 printf("pid1 unable to read the range 130:4, "
2498                        "recv %ld req %d\n", (unsigned long)nread, 4);
2499                 goto fail;
2500         } else {
2501                 printf("pid1 successfully read the range 130:4\n");
2502         }
2503
2504         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2505         if (!NT_STATUS_IS_OK(status)) {
2506                 printf("pid1 unable to write to the range 130:4, error was "
2507                        "%s\n", nt_errstr(status));
2508                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2509                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2510                         goto fail;
2511                 }
2512         } else {
2513                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2514                 goto fail;
2515         }
2516
2517         cli_setpid(cli1, 2);
2518
2519         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2520         if (!NT_STATUS_IS_OK(status)) {
2521                 printf("pid2 unable to read the range 130:4, error was %s\n",
2522                       nt_errstr(status));
2523                 goto fail;
2524         } else if (nread != 4) {
2525                 printf("pid2 unable to read the range 130:4, "
2526                        "recv %ld req %d\n", (unsigned long)nread, 4);
2527                 goto fail;
2528         } else {
2529                 printf("pid2 successfully read the range 130:4\n");
2530         }
2531
2532         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2533         if (!NT_STATUS_IS_OK(status)) {
2534                 printf("pid2 unable to write to the range 130:4, error was "
2535                        "%s\n", nt_errstr(status));
2536                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2537                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2538                         goto fail;
2539                 }
2540         } else {
2541                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2542                 goto fail;
2543         }
2544
2545         cli_setpid(cli1, 1);
2546         cli_unlock(cli1, fnum1, 130, 4);
2547
2548         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2549         if (!NT_STATUS_IS_OK(status)) {
2550                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2551                 goto fail;
2552         } else {
2553                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2554         }
2555
2556         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2557         if (!NT_STATUS_IS_OK(status)) {
2558                 printf("pid1 unable to read the range 130:4, error was %s\n",
2559                       nt_errstr(status));
2560                 goto fail;
2561         } else if (nread != 4) {
2562                 printf("pid1 unable to read the range 130:4, "
2563                        "recv %ld req %d\n", (unsigned long)nread, 4);
2564                 goto fail;
2565         } else {
2566                 printf("pid1 successfully read the range 130:4\n");
2567         }
2568
2569         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2570         if (!NT_STATUS_IS_OK(status)) {
2571                 printf("pid1 unable to write to the range 130:4, error was "
2572                        "%s\n", nt_errstr(status));
2573                 goto fail;
2574         } else {
2575                 printf("pid1 successfully wrote to the range 130:4\n");
2576         }
2577
2578         cli_setpid(cli1, 2);
2579
2580         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2581         if (!NT_STATUS_IS_OK(status)) {
2582                 printf("pid2 unable to read the range 130:4, error was "
2583                        "%s\n", nt_errstr(status));
2584                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2585                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2586                         goto fail;
2587                 }
2588         } else {
2589                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2590                        (unsigned long)nread);
2591                 goto fail;
2592         }
2593
2594         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2595         if (!NT_STATUS_IS_OK(status)) {
2596                 printf("pid2 unable to write to the range 130:4, error was "
2597                        "%s\n", nt_errstr(status));
2598                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2599                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2600                         goto fail;
2601                 }
2602         } else {
2603                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2604                 goto fail;
2605         }
2606
2607         cli_unlock(cli1, fnum1, 130, 0);
2608         correct = True;
2609
2610 fail:
2611         cli_close(cli1, fnum1);
2612         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2613         torture_close_connection(cli1);
2614
2615         printf("finished locktest7\n");
2616         return correct;
2617 }
2618
2619 /*
2620  * This demonstrates a problem with our use of GPFS share modes: A file
2621  * descriptor sitting in the pending close queue holding a GPFS share mode
2622  * blocks opening a file another time. Happens with Word 2007 temp files.
2623  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2624  * open is denied with NT_STATUS_SHARING_VIOLATION.
2625  */
2626
2627 static bool run_locktest8(int dummy)
2628 {
2629         struct cli_state *cli1;
2630         const char *fname = "\\lockt8.lck";
2631         uint16_t fnum1, fnum2;
2632         char buf[200];
2633         bool correct = False;
2634         NTSTATUS status;
2635
2636         if (!torture_open_connection(&cli1, 0)) {
2637                 return False;
2638         }
2639
2640         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2641
2642         printf("starting locktest8\n");
2643
2644         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2645
2646         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2647                           &fnum1);
2648         if (!NT_STATUS_IS_OK(status)) {
2649                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2650                 return false;
2651         }
2652
2653         memset(buf, 0, sizeof(buf));
2654
2655         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2656         if (!NT_STATUS_IS_OK(status)) {
2657                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2658                           nt_errstr(status));
2659                 goto fail;
2660         }
2661
2662         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2663         if (!NT_STATUS_IS_OK(status)) {
2664                 printf("Unable to apply read lock on range 1:1, error was "
2665                        "%s\n", nt_errstr(status));
2666                 goto fail;
2667         }
2668
2669         status = cli_close(cli1, fnum1);
2670         if (!NT_STATUS_IS_OK(status)) {
2671                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2672                 goto fail;
2673         }
2674
2675         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2676         if (!NT_STATUS_IS_OK(status)) {
2677                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2678                           nt_errstr(status));
2679                 goto fail;
2680         }
2681
2682         correct = true;
2683
2684 fail:
2685         cli_close(cli1, fnum1);
2686         cli_close(cli1, fnum2);
2687         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2688         torture_close_connection(cli1);
2689
2690         printf("finished locktest8\n");
2691         return correct;
2692 }
2693
2694 /*
2695  * This test is designed to be run in conjunction with
2696  * external NFS or POSIX locks taken in the filesystem.
2697  * It checks that the smbd server will block until the
2698  * lock is released and then acquire it. JRA.
2699  */
2700
2701 static bool got_alarm;
2702 static struct cli_state *alarm_cli;
2703
2704 static void alarm_handler(int dummy)
2705 {
2706         got_alarm = True;
2707 }
2708
2709 static void alarm_handler_parent(int dummy)
2710 {
2711         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2712 }
2713
2714 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2715 {
2716         int fd;
2717         char c = '\0';
2718         struct flock lock;
2719         const char *local_pathname = NULL;
2720         int ret;
2721
2722         local_pathname = talloc_asprintf(talloc_tos(),
2723                         "%s/%s", local_path, fname);
2724         if (!local_pathname) {
2725                 printf("child: alloc fail\n");
2726                 exit(1);
2727         }
2728
2729         unlink(local_pathname);
2730         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2731         if (fd == -1) {
2732                 printf("child: open of %s failed %s.\n",
2733                         local_pathname, strerror(errno));
2734                 exit(1);
2735         }
2736
2737         /* Now take a fcntl lock. */
2738         lock.l_type = F_WRLCK;
2739         lock.l_whence = SEEK_SET;
2740         lock.l_start = 0;
2741         lock.l_len = 4;
2742         lock.l_pid = getpid();
2743
2744         ret = fcntl(fd,F_SETLK,&lock);
2745         if (ret == -1) {
2746                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2747                         local_pathname, strerror(errno));
2748                 exit(1);
2749         } else {
2750                 printf("child: got lock 0:4 on file %s.\n",
2751                         local_pathname );
2752                 fflush(stdout);
2753         }
2754
2755         CatchSignal(SIGALRM, alarm_handler);
2756         alarm(5);
2757         /* Signal the parent. */
2758         if (write(write_fd, &c, 1) != 1) {
2759                 printf("child: start signal fail %s.\n",
2760                         strerror(errno));
2761                 exit(1);
2762         }
2763         alarm(0);
2764
2765         alarm(10);
2766         /* Wait for the parent to be ready. */
2767         if (read(read_fd, &c, 1) != 1) {
2768                 printf("child: reply signal fail %s.\n",
2769                         strerror(errno));
2770                 exit(1);
2771         }
2772         alarm(0);
2773
2774         sleep(5);
2775         close(fd);
2776         printf("child: released lock 0:4 on file %s.\n",
2777                 local_pathname );
2778         fflush(stdout);
2779         exit(0);
2780 }
2781
2782 static bool _run_locktest9X(const char *fname, int timeout)
2783 {
2784         struct cli_state *cli1;
2785         char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2786         uint16_t fnum;
2787         bool correct = False;
2788         int pipe_in[2], pipe_out[2];
2789         pid_t child_pid;
2790         char c = '\0';
2791         int ret;
2792         struct timeval start;
2793         double seconds;
2794         NTSTATUS status;
2795
2796         printf("starting locktest9X: %s\n", fname);
2797
2798         if (local_path == NULL) {
2799                 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2800                 return false;
2801         }
2802
2803         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2804                 return false;
2805         }
2806
2807         child_pid = fork();
2808         if (child_pid == -1) {
2809                 return false;
2810         }
2811
2812         if (child_pid == 0) {
2813                 /* Child. */
2814                 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2815                 exit(0);
2816         }
2817
2818         close(pipe_out[0]);
2819         close(pipe_in[1]);
2820         pipe_out[0] = -1;
2821         pipe_in[1] = -1;
2822
2823         /* Parent. */
2824         ret = read(pipe_in[0], &c, 1);
2825         if (ret != 1) {
2826                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2827                         strerror(errno));
2828                 return false;
2829         }
2830
2831         if (!torture_open_connection(&cli1, 0)) {
2832                 return false;
2833         }
2834
2835         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2836
2837         status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2838                           &fnum);
2839         if (!NT_STATUS_IS_OK(status)) {
2840                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2841                 return false;
2842         }
2843
2844         /* Ensure the child has the lock. */
2845         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2846         if (NT_STATUS_IS_OK(status)) {
2847                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2848                 goto fail;
2849         } else {
2850                 d_printf("Child has the lock.\n");
2851         }
2852
2853         /* Tell the child to wait 5 seconds then exit. */
2854         ret = write(pipe_out[1], &c, 1);
2855         if (ret != 1) {
2856                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2857                         strerror(errno));
2858                 goto fail;
2859         }
2860
2861         /* Wait 20 seconds for the lock. */
2862         alarm_cli = cli1;
2863         CatchSignal(SIGALRM, alarm_handler_parent);
2864         alarm(20);
2865
2866         start = timeval_current();
2867
2868         status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2869         if (!NT_STATUS_IS_OK(status)) {
2870                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2871                        "%s\n", nt_errstr(status));
2872                 goto fail_nofd;
2873         }
2874         alarm(0);
2875
2876         seconds = timeval_elapsed(&start);
2877
2878         printf("Parent got the lock after %.2f seconds.\n",
2879                 seconds);
2880
2881         status = cli_close(cli1, fnum);
2882         if (!NT_STATUS_IS_OK(status)) {
2883                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2884                 goto fail;
2885         }
2886
2887         correct = true;
2888
2889 fail:
2890         cli_close(cli1, fnum);
2891         torture_close_connection(cli1);
2892
2893 fail_nofd:
2894
2895         printf("finished locktest9X: %s\n", fname);
2896         return correct;
2897 }
2898
2899 static bool run_locktest9a(int dummy)
2900 {
2901         return _run_locktest9X("lock9a.dat", -1);
2902 }
2903
2904 static bool run_locktest9b(int dummy)
2905 {
2906         return _run_locktest9X("lock9b.dat", 10000);
2907 }
2908
2909 struct locktest10_state {
2910         bool ok;
2911         bool done;
2912 };
2913
2914 static void locktest10_lockingx_done(struct tevent_req *subreq);
2915 static void locktest10_read_andx_done(struct tevent_req *subreq);
2916
2917 static bool run_locktest10(int dummy)
2918 {
2919         struct tevent_context *ev = NULL;
2920         struct cli_state *cli1 = NULL;
2921         struct cli_state *cli2 = NULL;
2922         struct smb1_lock_element lck = { 0 };
2923         struct tevent_req *reqs[2] = { NULL };
2924         struct tevent_req *smbreqs[2] = { NULL };
2925         const char fname[] = "\\lockt10.lck";
2926         uint16_t fnum1, fnum2;
2927         bool ret = false;
2928         bool ok;
2929         uint8_t data = 1;
2930         struct locktest10_state state = { .ok = true };
2931         NTSTATUS status;
2932
2933         printf("starting locktest10\n");
2934
2935         ev = samba_tevent_context_init(NULL);
2936         if (ev == NULL) {
2937                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2938                 goto done;
2939         }
2940
2941         ok = torture_open_connection(&cli1, 0);
2942         if (!ok) {
2943                 goto done;
2944         }
2945         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2946
2947         ok = torture_open_connection(&cli2, 1);
2948         if (!ok) {
2949                 goto done;
2950         }
2951         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2952
2953         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2954         if (!NT_STATUS_IS_OK(status)) {
2955                 d_fprintf(stderr,
2956                           "cli_openx failed: %s\n",
2957                           nt_errstr(status));
2958                 goto done;
2959         }
2960
2961         status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2962         if (!NT_STATUS_IS_OK(status)) {
2963                 d_fprintf(stderr,
2964                           "cli_writeall failed: %s\n",
2965                           nt_errstr(status));
2966                 goto done;
2967         }
2968
2969         status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2970         if (!NT_STATUS_IS_OK(status)) {
2971                 d_fprintf(stderr,
2972                           "cli_openx failed: %s\n",
2973                           nt_errstr(status));
2974                 goto done;
2975         }
2976
2977         status = cli_locktype(
2978                 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2979         if (!NT_STATUS_IS_OK(status)) {
2980                 d_fprintf(stderr,
2981                           "cli_locktype failed: %s\n",
2982                           nt_errstr(status));
2983                 goto done;
2984         }
2985
2986         lck = (struct smb1_lock_element) {
2987                 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2988         };
2989
2990         reqs[0] = cli_lockingx_create(
2991                 ev,                             /* mem_ctx */
2992                 ev,                             /* tevent_context */
2993                 cli1,                           /* cli */
2994                 fnum1,                          /* fnum */
2995                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
2996                 0,                              /* newoplocklevel */
2997                 1,                              /* timeout */
2998                 0,                              /* num_unlocks */
2999                 NULL,                           /* unlocks */
3000                 1,                              /* num_locks */
3001                 &lck,                           /* locks */
3002                 &smbreqs[0]);                   /* psmbreq */
3003         if (reqs[0] == NULL) {
3004                 d_fprintf(stderr, "cli_lockingx_create failed\n");
3005                 goto done;
3006         }
3007         tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3008
3009         reqs[1] = cli_read_andx_create(
3010                 ev,             /* mem_ctx */
3011                 ev,             /* ev */
3012                 cli1,           /* cli */
3013                 fnum1,          /* fnum */
3014                 0,              /* offset */
3015                 1,              /* size */
3016                 &smbreqs[1]);   /* psmbreq */
3017         if (reqs[1] == NULL) {
3018                 d_fprintf(stderr, "cli_read_andx_create failed\n");
3019                 goto done;
3020         }
3021         tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3022
3023         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3024         if (!NT_STATUS_IS_OK(status)) {
3025                 d_fprintf(stderr,
3026                           "smb1cli_req_chain_submit failed: %s\n",
3027                           nt_errstr(status));
3028                 goto done;
3029         }
3030
3031         while (!state.done) {
3032                 tevent_loop_once(ev);
3033         }
3034
3035         torture_close_connection(cli1);
3036
3037         if (state.ok) {
3038                 ret = true;
3039         }
3040 done:
3041         return ret;
3042 }
3043
3044 static void locktest10_lockingx_done(struct tevent_req *subreq)
3045 {
3046         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3047         NTSTATUS status;
3048
3049         status = cli_lockingx_recv(subreq);
3050         TALLOC_FREE(subreq);
3051
3052         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3053                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3054                 state->ok = false;
3055         }
3056 }
3057
3058 static void locktest10_read_andx_done(struct tevent_req *subreq)
3059 {
3060         struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3061         ssize_t received = -1;
3062         uint8_t *rcvbuf = NULL;
3063         NTSTATUS status;
3064
3065         status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3066
3067         if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3068                 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3069                 state->ok = false;
3070         }
3071
3072         state->done = true;
3073         TALLOC_FREE(subreq);
3074 }
3075
3076 static bool run_locktest11(int dummy)
3077 {
3078         struct cli_state *cli1;
3079         const char *fname = "\\lockt11.lck";
3080         NTSTATUS status;
3081         uint16_t fnum;
3082         bool ret = false;
3083
3084         if (!torture_open_connection(&cli1, 0)) {
3085                 return false;
3086         }
3087
3088         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3089
3090         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3091
3092         status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3093         if (!NT_STATUS_IS_OK(status)) {
3094                 d_fprintf(stderr,
3095                           "cli_openx returned %s\n",
3096                           nt_errstr(status));
3097                 return false;
3098         }
3099
3100         /*
3101          * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3102          * returns NT_STATUS_OK
3103          */
3104
3105         status = cli_lockingx(
3106                 cli1,                           /* cli */
3107                 fnum,                           /* fnum */
3108                 LOCKING_ANDX_CANCEL_LOCK,       /* typeoflock */
3109                 0,                              /* newoplocklevel */
3110                 0,                              /* timeout */
3111                 0,                              /* num_unlocks */
3112                 NULL,                           /* unlocks */
3113                 0,                              /* num_locks */
3114                 NULL);                          /* locks */
3115
3116         if (!NT_STATUS_IS_OK(status)) {
3117                 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3118                 goto fail;
3119         }
3120
3121         ret = true;
3122 fail:
3123         cli_close(cli1, fnum);
3124         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3125
3126         return ret;
3127 }
3128
3129 struct deferred_close_state {
3130         struct tevent_context *ev;
3131         struct cli_state *cli;
3132         uint16_t fnum;
3133 };
3134
3135 static void deferred_close_waited(struct tevent_req *subreq);
3136 static void deferred_close_done(struct tevent_req *subreq);
3137
3138 static struct tevent_req *deferred_close_send(
3139         TALLOC_CTX *mem_ctx,
3140         struct tevent_context *ev,
3141         int wait_secs,
3142         struct cli_state *cli,
3143         uint16_t fnum)
3144 {
3145         struct tevent_req *req = NULL, *subreq = NULL;
3146         struct deferred_close_state *state = NULL;
3147         struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3148
3149         req = tevent_req_create(
3150                 mem_ctx, &state, struct deferred_close_state);
3151         if (req == NULL) {
3152                 return NULL;
3153         }
3154         state->ev = ev;
3155         state->cli = cli;
3156         state->fnum = fnum;
3157
3158         subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3159         if (tevent_req_nomem(subreq, req)) {
3160                 return tevent_req_post(req, ev);
3161         }
3162         tevent_req_set_callback(subreq, deferred_close_waited, req);
3163         return req;
3164 }
3165
3166 static void deferred_close_waited(struct tevent_req *subreq)
3167 {
3168         struct tevent_req *req = tevent_req_callback_data(
3169                 subreq, struct tevent_req);
3170         struct deferred_close_state *state = tevent_req_data(
3171                 req, struct deferred_close_state);
3172         bool ok;
3173
3174         ok = tevent_wakeup_recv(subreq);
3175         TALLOC_FREE(subreq);
3176         if (!ok) {
3177                 tevent_req_oom(req);
3178                 return;
3179         }
3180
3181         subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3182         if (tevent_req_nomem(subreq, req)) {
3183                 return;
3184         }
3185         tevent_req_set_callback(subreq, deferred_close_done, req);
3186 }
3187
3188 static void deferred_close_done(struct tevent_req *subreq)
3189 {
3190         NTSTATUS status = cli_close_recv(subreq);
3191         tevent_req_simple_finish_ntstatus(subreq, status);
3192 }
3193
3194 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3195 {
3196         return tevent_req_simple_recv_ntstatus(req);
3197 }
3198
3199 struct lockread_state {
3200         struct smb1_lock_element lck;
3201         struct tevent_req *reqs[2];
3202         struct tevent_req *smbreqs[2];
3203         NTSTATUS lock_status;
3204         NTSTATUS read_status;
3205         uint8_t *readbuf;
3206 };
3207
3208 static void lockread_lockingx_done(struct tevent_req *subreq);
3209 static void lockread_read_andx_done(struct tevent_req *subreq);
3210
3211 static struct tevent_req *lockread_send(
3212         TALLOC_CTX *mem_ctx,
3213         struct tevent_context *ev,
3214         struct cli_state *cli,
3215         uint16_t fnum)
3216 {
3217         struct tevent_req *req = NULL;
3218         struct lockread_state *state = NULL;
3219         NTSTATUS status;
3220
3221         req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3222         if (req == NULL) {
3223                 return NULL;
3224         }
3225
3226         state->lck = (struct smb1_lock_element) {
3227                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3228         };
3229
3230         state->reqs[0] = cli_lockingx_create(
3231                 ev,                             /* mem_ctx */
3232                 ev,                             /* tevent_context */
3233                 cli,                            /* cli */
3234                 fnum,                           /* fnum */
3235                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3236                 0,                              /* newoplocklevel */
3237                 10000,                          /* timeout */
3238                 0,                              /* num_unlocks */
3239                 NULL,                           /* unlocks */
3240                 1,                              /* num_locks */
3241                 &state->lck,                    /* locks */
3242                 &state->smbreqs[0]);            /* psmbreq */
3243         if (tevent_req_nomem(state->reqs[0], req)) {
3244                 return tevent_req_post(req, ev);
3245         }
3246         tevent_req_set_callback(
3247                 state->reqs[0], lockread_lockingx_done, req);
3248
3249         state->reqs[1] = cli_read_andx_create(
3250                 ev,             /* mem_ctx */
3251                 ev,             /* ev */
3252                 cli,            /* cli */
3253                 fnum,           /* fnum */
3254                 0,              /* offset */
3255                 1,              /* size */
3256                 &state->smbreqs[1]);    /* psmbreq */
3257         if (tevent_req_nomem(state->reqs[1], req)) {
3258                 return tevent_req_post(req, ev);
3259         }
3260         tevent_req_set_callback(
3261                 state->reqs[1], lockread_read_andx_done, req);
3262
3263         status = smb1cli_req_chain_submit(state->smbreqs, 2);
3264         if (tevent_req_nterror(req, status)) {
3265                 return tevent_req_post(req, ev);
3266         }
3267         return req;
3268 }
3269
3270 static void lockread_lockingx_done(struct tevent_req *subreq)
3271 {
3272         struct tevent_req *req = tevent_req_callback_data(
3273                 subreq, struct tevent_req);
3274         struct lockread_state *state = tevent_req_data(
3275                 req, struct lockread_state);
3276         state->lock_status = cli_lockingx_recv(subreq);
3277         TALLOC_FREE(subreq);
3278         d_fprintf(stderr,
3279                   "lockingx returned %s\n",
3280                   nt_errstr(state->lock_status));
3281 }
3282
3283 static void lockread_read_andx_done(struct tevent_req *subreq)
3284 {
3285         struct tevent_req *req = tevent_req_callback_data(
3286                 subreq, struct tevent_req);
3287         struct lockread_state *state = tevent_req_data(
3288                 req, struct lockread_state);
3289         ssize_t received = -1;
3290         uint8_t *rcvbuf = NULL;
3291
3292         state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3293
3294         d_fprintf(stderr,
3295                   "read returned %s\n",
3296                   nt_errstr(state->read_status));
3297
3298         if (!NT_STATUS_IS_OK(state->read_status)) {
3299                 TALLOC_FREE(subreq);
3300                 tevent_req_done(req);
3301                 return;
3302         }
3303
3304         if (received > 0) {
3305                 state->readbuf = talloc_memdup(state, rcvbuf, received);
3306                 TALLOC_FREE(subreq);
3307                 if (tevent_req_nomem(state->readbuf, req)) {
3308                         return;
3309                 }
3310         }
3311         TALLOC_FREE(subreq);
3312         tevent_req_done(req);
3313 }
3314
3315 static NTSTATUS lockread_recv(
3316         struct tevent_req *req,
3317         NTSTATUS *lock_status,
3318         NTSTATUS *read_status,
3319         TALLOC_CTX *mem_ctx,
3320         uint8_t **read_buf)
3321 {
3322         struct lockread_state *state = tevent_req_data(
3323                 req, struct lockread_state);
3324         NTSTATUS status;
3325
3326         if (tevent_req_is_nterror(req, &status)) {
3327                 return status;
3328         }
3329
3330         *lock_status = state->lock_status;
3331         *read_status = state->read_status;
3332         if (state->readbuf != NULL) {
3333                 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3334         } else {
3335                 *read_buf = NULL;
3336         }
3337
3338         return NT_STATUS_OK;
3339 }
3340
3341 struct lock12_state {
3342         uint8_t dummy;
3343 };
3344
3345 static void lock12_closed(struct tevent_req *subreq);
3346 static void lock12_read(struct tevent_req *subreq);
3347
3348 static struct tevent_req *lock12_send(
3349         TALLOC_CTX *mem_ctx,
3350         struct tevent_context *ev,
3351         struct cli_state *cli,
3352         uint16_t fnum1,
3353         uint16_t fnum2)
3354 {
3355         struct tevent_req *req = NULL, *subreq = NULL;
3356         struct lock12_state *state = NULL;
3357
3358         req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3359         if (req == NULL) {
3360                 return NULL;
3361         }
3362
3363         subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3364         if (tevent_req_nomem(subreq, req)) {
3365                 return tevent_req_post(req, ev);
3366         }
3367         tevent_req_set_callback(subreq, lock12_closed, req);
3368
3369         subreq = lockread_send(state, ev, cli, fnum2);
3370         if (tevent_req_nomem(subreq, req)) {
3371                 return tevent_req_post(req, ev);
3372         }
3373         tevent_req_set_callback(subreq, lock12_read, req);
3374
3375         return req;
3376 }
3377
3378 static void lock12_closed(struct tevent_req *subreq)
3379 {
3380         struct tevent_req *req = tevent_req_callback_data(
3381                 subreq, struct tevent_req);
3382         NTSTATUS status;
3383
3384         status = deferred_close_recv(subreq);
3385         TALLOC_FREE(subreq);
3386         DBG_DEBUG("close returned %s\n", nt_errstr(status));
3387         if (tevent_req_nterror(req, status)) {
3388                 return;
3389         }
3390 }
3391
3392 static void lock12_read(struct tevent_req *subreq)
3393 {
3394         struct tevent_req *req = tevent_req_callback_data(
3395                 subreq, struct tevent_req);
3396         struct lock12_state *state = tevent_req_data(
3397                 req, struct lock12_state);
3398         NTSTATUS status, lock_status, read_status;
3399         uint8_t *buf = NULL;
3400
3401         status = lockread_recv(
3402                 subreq, &lock_status, &read_status, state, &buf);
3403         TALLOC_FREE(subreq);
3404         if (tevent_req_nterror(req, status) ||
3405             tevent_req_nterror(req, lock_status) ||
3406             tevent_req_nterror(req, read_status)) {
3407                 return;
3408         }
3409         tevent_req_done(req);
3410 }
3411
3412 static NTSTATUS lock12_recv(struct tevent_req *req)
3413
3414 {
3415         NTSTATUS status;
3416
3417         if (tevent_req_is_nterror(req, &status)) {
3418                 return status;
3419         }
3420         return NT_STATUS_OK;
3421 }
3422
3423 static bool run_locktest12(int dummy)
3424 {
3425         struct tevent_context *ev = NULL;
3426         struct tevent_req *req = NULL;
3427         struct cli_state *cli = NULL;
3428         const char fname[] = "\\lockt12.lck";
3429         uint16_t fnum1, fnum2;
3430         bool ret = false;
3431         bool ok;
3432         uint8_t data = 1;
3433         NTSTATUS status;
3434
3435         printf("starting locktest12\n");
3436
3437         ev = samba_tevent_context_init(NULL);
3438         if (ev == NULL) {
3439                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3440                 goto done;
3441         }
3442
3443         ok = torture_open_connection(&cli, 0);
3444         if (!ok) {
3445                 goto done;
3446         }
3447         smbXcli_conn_set_sockopt(cli->conn, sockops);
3448
3449         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3450         if (!NT_STATUS_IS_OK(status)) {
3451                 d_fprintf(stderr,
3452                           "cli_openx failed: %s\n",
3453                           nt_errstr(status));
3454                 goto done;
3455         }
3456
3457         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3458         if (!NT_STATUS_IS_OK(status)) {
3459                 d_fprintf(stderr,
3460                           "cli_openx failed: %s\n",
3461                           nt_errstr(status));
3462                 goto done;
3463         }
3464
3465         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3466         if (!NT_STATUS_IS_OK(status)) {
3467                 d_fprintf(stderr,
3468                           "cli_writeall failed: %s\n",
3469                           nt_errstr(status));
3470                 goto done;
3471         }
3472
3473         status = cli_locktype(
3474                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3475         if (!NT_STATUS_IS_OK(status)) {
3476                 d_fprintf(stderr,
3477                           "cli_locktype failed: %s\n",
3478                           nt_errstr(status));
3479                 goto done;
3480         }
3481
3482         req = lock12_send(ev, ev, cli, fnum1, fnum2);
3483         if (req == NULL) {
3484                 d_fprintf(stderr, "lock12_send failed\n");
3485                 goto done;
3486         }
3487
3488         ok = tevent_req_poll_ntstatus(req, ev, &status);
3489         if (!ok) {
3490                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3491                 goto done;
3492         }
3493
3494         if (!NT_STATUS_IS_OK(status)) {
3495                 d_fprintf(stderr,
3496                           "tevent_req_poll_ntstatus returned %s\n",
3497                           nt_errstr(status));
3498                 goto done;
3499         }
3500
3501         status = lock12_recv(req);
3502         if (!NT_STATUS_IS_OK(status)) {
3503                 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3504                 goto done;
3505         }
3506
3507         ret = true;
3508 done:
3509         if (cli != NULL) {
3510                 torture_close_connection(cli);
3511         }
3512         return ret;
3513 }
3514
3515 struct lock_ntcancel_state {
3516         struct timeval start;
3517         struct smb1_lock_element lck;
3518         struct tevent_req *subreq;
3519 };
3520
3521 static void lock_ntcancel_waited(struct tevent_req *subreq);
3522 static void lock_ntcancel_done(struct tevent_req *subreq);
3523
3524 static struct tevent_req *lock_ntcancel_send(
3525         TALLOC_CTX *mem_ctx,
3526         struct tevent_context *ev,
3527         struct cli_state *cli,
3528         uint16_t fnum)
3529 {
3530         struct tevent_req *req = NULL, *subreq = NULL;
3531         struct lock_ntcancel_state *state = NULL;
3532
3533         req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3534         if (req == NULL) {
3535                 return NULL;
3536         }
3537         state->lck = (struct smb1_lock_element) {
3538                 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3539         };
3540         state->start = timeval_current();
3541
3542         state->subreq = cli_lockingx_send(
3543                 state,                          /* mem_ctx */
3544                 ev,                             /* tevent_context */
3545                 cli,                            /* cli */
3546                 fnum,                           /* fnum */
3547                 LOCKING_ANDX_EXCLUSIVE_LOCK,    /* typeoflock */
3548                 0,                              /* newoplocklevel */
3549                 10000,                          /* timeout */
3550                 0,                              /* num_unlocks */
3551                 NULL,                           /* unlocks */
3552                 1,                              /* num_locks */
3553                 &state->lck);                   /* locks */
3554         if (tevent_req_nomem(state->subreq, req)) {
3555                 return tevent_req_post(req, ev);
3556         }
3557         tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3558
3559         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3560         if (tevent_req_nomem(subreq, req)) {
3561                 return tevent_req_post(req, ev);
3562         }
3563         tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3564         return req;
3565 }
3566
3567 static void lock_ntcancel_waited(struct tevent_req *subreq)
3568 {
3569         struct tevent_req *req = tevent_req_callback_data(
3570                 subreq, struct tevent_req);
3571         struct lock_ntcancel_state *state = tevent_req_data(
3572                 req, struct lock_ntcancel_state);
3573         bool ok;
3574
3575         ok = tevent_wakeup_recv(subreq);
3576         TALLOC_FREE(subreq);
3577         if (!ok) {
3578                 tevent_req_oom(req);
3579                 return;
3580         }
3581
3582         ok = tevent_req_cancel(state->subreq);
3583         if (!ok) {
3584                 d_fprintf(stderr, "Could not cancel subreq\n");
3585                 tevent_req_oom(req);
3586                 return;
3587         }
3588 }
3589
3590 static void lock_ntcancel_done(struct tevent_req *subreq)
3591 {
3592         struct tevent_req *req = tevent_req_callback_data(
3593                 subreq, struct tevent_req);
3594         struct lock_ntcancel_state *state = tevent_req_data(
3595                 req, struct lock_ntcancel_state);
3596         NTSTATUS status;
3597         double elapsed;
3598
3599         status = cli_lockingx_recv(subreq);
3600         TALLOC_FREE(subreq);
3601
3602         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3603                 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3604                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3605                 return;
3606         }
3607
3608         elapsed = timeval_elapsed(&state->start);
3609
3610         if (elapsed > 3) {
3611                 d_printf("cli_lockingx was too slow, cancel did not work\n");
3612                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3613                 return;
3614         }
3615
3616         tevent_req_done(req);
3617 }
3618
3619 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3620 {
3621         return tevent_req_simple_recv_ntstatus(req);
3622 }
3623
3624 static bool run_locktest13(int dummy)
3625 {
3626         struct tevent_context *ev = NULL;
3627         struct tevent_req *req = NULL;
3628         struct cli_state *cli = NULL;
3629         const char fname[] = "\\lockt13.lck";
3630         uint16_t fnum1, fnum2;
3631         bool ret = false;
3632         bool ok;
3633         uint8_t data = 1;
3634         NTSTATUS status;
3635
3636         printf("starting locktest13\n");
3637
3638         ev = samba_tevent_context_init(NULL);
3639         if (ev == NULL) {
3640                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3641                 goto done;
3642         }
3643
3644         ok = torture_open_connection(&cli, 0);
3645         if (!ok) {
3646                 goto done;
3647         }
3648         smbXcli_conn_set_sockopt(cli->conn, sockops);
3649
3650         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3651         if (!NT_STATUS_IS_OK(status)) {
3652                 d_fprintf(stderr,
3653                           "cli_openx failed: %s\n",
3654                           nt_errstr(status));
3655                 goto done;
3656         }
3657
3658         status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3659         if (!NT_STATUS_IS_OK(status)) {
3660                 d_fprintf(stderr,
3661                           "cli_openx failed: %s\n",
3662                           nt_errstr(status));
3663                 goto done;
3664         }
3665
3666         status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3667         if (!NT_STATUS_IS_OK(status)) {
3668                 d_fprintf(stderr,
3669                           "cli_writeall failed: %s\n",
3670                           nt_errstr(status));
3671                 goto done;
3672         }
3673
3674         status = cli_locktype(
3675                 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3676         if (!NT_STATUS_IS_OK(status)) {
3677                 d_fprintf(stderr,
3678                           "cli_locktype failed: %s\n",
3679                           nt_errstr(status));
3680                 goto done;
3681         }
3682
3683         req = lock_ntcancel_send(ev, ev, cli, fnum2);
3684         if (req == NULL) {
3685                 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3686                 goto done;
3687         }
3688
3689         ok = tevent_req_poll_ntstatus(req, ev, &status);
3690         if (!ok) {
3691                 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3692                 goto done;
3693         }
3694
3695         if (!NT_STATUS_IS_OK(status)) {
3696                 d_fprintf(stderr,
3697                           "tevent_req_poll_ntstatus returned %s\n",
3698                           nt_errstr(status));
3699                 goto done;
3700         }
3701
3702         status = lock_ntcancel_recv(req);
3703         if (!NT_STATUS_IS_OK(status)) {
3704                 d_fprintf(stderr,
3705                           "lock_ntcancel returned %s\n",
3706                           nt_errstr(status));
3707                 goto done;
3708         }
3709
3710         ret = true;
3711 done:
3712         if (cli != NULL) {
3713                 torture_close_connection(cli);
3714         }
3715         return ret;
3716 }
3717
3718 /*
3719 test whether fnums and tids open on one VC are available on another (a major
3720 security hole)
3721 */
3722 static bool run_fdpasstest(int dummy)
3723 {
3724         struct cli_state *cli1, *cli2;
3725         const char *fname = "\\fdpass.tst";
3726         uint16_t fnum1;
3727         char buf[1024];
3728         NTSTATUS status;
3729
3730         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3731                 return False;
3732         }
3733         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3734         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3735
3736         printf("starting fdpasstest\n");
3737
3738         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3739
3740         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3741                           &fnum1);
3742         if (!NT_STATUS_IS_OK(status)) {
3743                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3744                 return False;
3745         }
3746
3747         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3748                               13, NULL);
3749         if (!NT_STATUS_IS_OK(status)) {
3750                 printf("write failed (%s)\n", nt_errstr(status));
3751                 return False;
3752         }
3753
3754         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3755         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3756         cli_setpid(cli2, cli_getpid(cli1));
3757
3758         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3759                 printf("read succeeded! nasty security hole [%s]\n", buf);
3760                 return false;
3761         }
3762
3763         cli_close(cli1, fnum1);
3764         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3765
3766         torture_close_connection(cli1);
3767         torture_close_connection(cli2);
3768
3769         printf("finished fdpasstest\n");
3770         return True;
3771 }
3772
3773 static bool run_fdsesstest(int dummy)
3774 {
3775         struct cli_state *cli;
3776         uint16_t new_vuid;
3777         uint16_t saved_vuid;
3778         uint32_t new_cnum;
3779         uint32_t saved_cnum;
3780         const char *fname = "\\fdsess.tst";
3781         const char *fname1 = "\\fdsess1.tst";
3782         uint16_t fnum1;
3783         uint16_t fnum2;
3784         char buf[1024];
3785         bool ret = True;
3786         NTSTATUS status;
3787
3788         if (!torture_open_connection(&cli, 0))
3789                 return False;
3790         smbXcli_conn_set_sockopt(cli->conn, sockops);
3791
3792         if (!torture_cli_session_setup2(cli, &new_vuid))
3793                 return False;
3794
3795         saved_cnum = cli_state_get_tid(cli);
3796         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3797                 return False;
3798         new_cnum = cli_state_get_tid(cli);
3799         cli_state_set_tid(cli, saved_cnum);
3800
3801         printf("starting fdsesstest\n");
3802
3803         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3805
3806         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3807         if (!NT_STATUS_IS_OK(status)) {
3808                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3809                 return False;
3810         }
3811
3812         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3813                               NULL);
3814         if (!NT_STATUS_IS_OK(status)) {
3815                 printf("write failed (%s)\n", nt_errstr(status));
3816                 return False;
3817         }
3818
3819         saved_vuid = cli_state_get_uid(cli);
3820         cli_state_set_uid(cli, new_vuid);
3821
3822         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3823                 printf("read succeeded with different vuid! "
3824                        "nasty security hole [%s]\n", buf);
3825                 ret = false;
3826         }
3827         /* Try to open a file with different vuid, samba cnum. */
3828         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3829                 printf("create with different vuid, same cnum succeeded.\n");
3830                 cli_close(cli, fnum2);
3831                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3832         } else {
3833                 printf("create with different vuid, same cnum failed.\n");
3834                 printf("This will cause problems with service clients.\n");
3835                 ret = False;
3836         }
3837
3838         cli_state_set_uid(cli, saved_vuid);
3839
3840         /* Try with same vuid, different cnum. */
3841         cli_state_set_tid(cli, new_cnum);
3842
3843         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3844                 printf("read succeeded with different cnum![%s]\n", buf);
3845                 ret = false;
3846         }
3847
3848         cli_state_set_tid(cli, saved_cnum);
3849         cli_close(cli, fnum1);
3850         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3851
3852         torture_close_connection(cli);
3853
3854         printf("finished fdsesstest\n");
3855         return ret;
3856 }
3857
3858 /*
3859   This test checks that 
3860
3861   1) the server does not allow an unlink on a file that is open
3862 */
3863 static bool run_unlinktest(int dummy)
3864 {
3865         struct cli_state *cli;
3866         const char *fname = "\\unlink.tst";
3867         uint16_t fnum;
3868         bool correct = True;
3869         NTSTATUS status;
3870
3871         if (!torture_open_connection(&cli, 0)) {
3872                 return False;
3873         }
3874
3875         smbXcli_conn_set_sockopt(cli->conn, sockops);
3876
3877         printf("starting unlink test\n");
3878
3879         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3880
3881         cli_setpid(cli, 1);
3882
3883         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3884         if (!NT_STATUS_IS_OK(status)) {
3885                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3886                 return False;
3887         }
3888
3889         status = cli_unlink(cli, fname,
3890                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3891         if (NT_STATUS_IS_OK(status)) {
3892                 printf("error: server allowed unlink on an open file\n");
3893                 correct = False;
3894         } else {
3895                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3896                                       NT_STATUS_SHARING_VIOLATION);
3897         }
3898
3899         cli_close(cli, fnum);
3900         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3901
3902         if (!torture_close_connection(cli)) {
3903                 correct = False;
3904         }
3905
3906         printf("unlink test finished\n");
3907
3908         return correct;
3909 }
3910
3911
3912 /*
3913 test how many open files this server supports on the one socket
3914 */
3915 static bool run_maxfidtest(int dummy)
3916 {
3917         struct cli_state *cli;
3918         fstring fname;
3919         uint16_t fnums[0x11000];
3920         int i;
3921         int retries=4;
3922         bool correct = True;
3923         NTSTATUS status;
3924
3925         cli = current_cli;
3926
3927         if (retries <= 0) {
3928                 printf("failed to connect\n");
3929                 return False;
3930         }
3931
3932         smbXcli_conn_set_sockopt(cli->conn, sockops);
3933
3934         for (i=0; i<0x11000; i++) {
3935                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3936                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3937                                   &fnums[i]);
3938                 if (!NT_STATUS_IS_OK(status)) {
3939                         printf("open of %s failed (%s)\n", 
3940                                fname, nt_errstr(status));
3941                         printf("maximum fnum is %d\n", i);
3942                         break;
3943                 }
3944                 printf("%6d\r", i);
3945         }
3946         printf("%6d\n", i);
3947         i--;
3948
3949         printf("cleaning up\n");
3950         for (;i>=0;i--) {
3951                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3952                 cli_close(cli, fnums[i]);
3953
3954                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3955                 if (!NT_STATUS_IS_OK(status)) {
3956                         printf("unlink of %s failed (%s)\n", 
3957                                fname, nt_errstr(status));
3958                         correct = False;
3959                 }
3960                 printf("%6d\r", i);
3961         }
3962         printf("%6d\n", 0);
3963
3964         printf("maxfid test finished\n");
3965         if (!torture_close_connection(cli)) {
3966                 correct = False;
3967         }
3968         return correct;
3969 }
3970
3971 /* generate a random buffer */
3972 static void rand_buf(char *buf, int len)
3973 {
3974         while (len--) {
3975                 *buf = (char)sys_random();
3976                 buf++;
3977         }
3978 }
3979
3980 /* send smb negprot commands, not reading the response */
3981 static bool run_negprot_nowait(int dummy)
3982 {
3983         struct tevent_context *ev;
3984         int i;
3985         struct cli_state *cli;
3986         bool correct = True;
3987
3988         printf("starting negprot nowait test\n");
3989
3990         ev = samba_tevent_context_init(talloc_tos());
3991         if (ev == NULL) {
3992                 return false;
3993         }
3994
3995         if (!(cli = open_nbt_connection())) {
3996                 TALLOC_FREE(ev);
3997                 return False;
3998         }
3999
4000         for (i=0;i<50000;i++) {
4001                 struct tevent_req *req;
4002
4003                 req = smbXcli_negprot_send(
4004                         ev,
4005                         ev,
4006                         cli->conn,
4007                         cli->timeout,
4008                         PROTOCOL_CORE,
4009                         PROTOCOL_NT1,
4010                         0,
4011                         NULL);
4012                 if (req == NULL) {
4013                         TALLOC_FREE(ev);
4014                         return false;
4015                 }
4016                 if (!tevent_req_poll(req, ev)) {
4017                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4018                                   strerror(errno));
4019                         TALLOC_FREE(ev);
4020                         return false;
4021                 }
4022                 TALLOC_FREE(req);
4023         }
4024
4025         if (torture_close_connection(cli)) {
4026                 correct = False;
4027         }
4028
4029         printf("finished negprot nowait test\n");
4030
4031         return correct;
4032 }
4033
4034 /* send smb negprot commands, not reading the response */
4035 static bool run_bad_nbt_session(int dummy)
4036 {
4037         struct nmb_name called, calling;
4038         struct sockaddr_storage ss;
4039         NTSTATUS status;
4040         int fd;
4041         bool ret;
4042
4043         printf("starting bad nbt session test\n");
4044
4045         make_nmb_name(&calling, myname, 0x0);
4046         make_nmb_name(&called , host, 0x20);
4047
4048         if (!resolve_name(host, &ss, 0x20, true)) {
4049                 d_fprintf(stderr, "Could not resolve name %s\n", host);
4050                 return false;
4051         }
4052
4053         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4054         if (!NT_STATUS_IS_OK(status)) {
4055                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4056                           nt_errstr(status));
4057                 return false;
4058         }
4059
4060         ret = cli_bad_session_request(fd, &calling, &called);
4061         close(fd);
4062         if (!ret) {
4063                 d_fprintf(stderr, "open_socket_out failed: %s\n",
4064                           nt_errstr(status));
4065                 return false;
4066         }
4067
4068         printf("finished bad nbt session test\n");
4069         return true;
4070 }
4071
4072 /* send random IPC commands */
4073 static bool run_randomipc(int dummy)
4074 {
4075         char *rparam = NULL;
4076         char *rdata = NULL;
4077         unsigned int rdrcnt,rprcnt;
4078         char param[1024];
4079         int api, param_len, i;
4080         struct cli_state *cli;
4081         bool correct = True;
4082         int count = 50000;
4083
4084         printf("starting random ipc test\n");
4085
4086         if (!torture_open_connection(&cli, 0)) {
4087                 return False;
4088         }
4089
4090         for (i=0;i<count;i++) {
4091                 api = sys_random() % 500;
4092                 param_len = (sys_random() % 64);
4093
4094                 rand_buf(param, param_len);
4095
4096                 SSVAL(param,0,api); 
4097
4098                 cli_api(cli, 
4099                         param, param_len, 8,  
4100                         NULL, 0, CLI_BUFFER_SIZE,
4101                         &rparam, &rprcnt,     
4102                         &rdata, &rdrcnt);
4103                 if (i % 100 == 0) {
4104                         printf("%d/%d\r", i,count);
4105                 }
4106         }
4107         printf("%d/%d\n", i, count);
4108
4109         if (!torture_close_connection(cli)) {
4110                 correct = False;
4111         }
4112
4113         SAFE_FREE(rparam);
4114         SAFE_FREE(rdata);
4115
4116         printf("finished random ipc test\n");
4117
4118         return correct;
4119 }
4120
4121
4122
4123 static void browse_callback(const char *sname, uint32_t stype,
4124                             const char *comment, void *state)
4125 {
4126         printf("\t%20.20s %08x %s\n", sname, stype, comment);
4127 }
4128
4129
4130
4131 /*
4132   This test checks the browse list code
4133
4134 */
4135 static bool run_browsetest(int dummy)
4136 {
4137         static struct cli_state *cli;
4138         bool correct = True;
4139
4140         printf("starting browse test\n");
4141
4142         if (!torture_open_connection(&cli, 0)) {
4143                 return False;
4144         }
4145
4146         printf("domain list:\n");
4147         cli_NetServerEnum(cli, cli->server_domain, 
4148                           SV_TYPE_DOMAIN_ENUM,
4149                           browse_callback, NULL);
4150
4151         printf("machine list:\n");
4152         cli_NetServerEnum(cli, cli->server_domain, 
4153                           SV_TYPE_ALL,
4154                           browse_callback, NULL);
4155
4156         if (!torture_close_connection(cli)) {
4157                 correct = False;
4158         }
4159
4160         printf("browse test finished\n");
4161
4162         return correct;
4163
4164 }
4165
4166 static bool check_attributes(struct cli_state *cli,
4167                                 const char *fname,
4168                                 uint32_t expected_attrs)
4169 {
4170         uint32_t attrs = 0;
4171         NTSTATUS status = cli_getatr(cli,
4172                                 fname,
4173                                 &attrs,
4174                                 NULL,
4175                                 NULL);
4176         if (!NT_STATUS_IS_OK(status)) {
4177                 printf("cli_getatr failed with %s\n",
4178                         nt_errstr(status));
4179                 return false;
4180         }
4181         if (attrs != expected_attrs) {
4182                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4183                         (unsigned int)attrs,
4184                         (unsigned int)expected_attrs);
4185                 return false;
4186         }
4187         return true;
4188 }
4189
4190 /*
4191   This checks how the getatr calls works
4192 */
4193 static bool run_attrtest(int dummy)
4194 {
4195         struct cli_state *cli;
4196         uint16_t fnum;
4197         time_t t, t2;
4198         const char *fname = "\\attrib123456789.tst";
4199         bool correct = True;
4200         NTSTATUS status;
4201
4202         printf("starting attrib test\n");
4203
4204         if (!torture_open_connection(&cli, 0)) {
4205                 return False;
4206         }
4207
4208         /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4209         status = cli_unlink(cli, fname, 0x20000);
4210         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4211                 correct = false;
4212                 goto out;
4213         }
4214
4215         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4216         cli_openx(cli, fname, 
4217                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4218         cli_close(cli, fnum);
4219
4220         status = cli_getatr(cli, fname, NULL, NULL, &t);
4221         if (!NT_STATUS_IS_OK(status)) {
4222                 printf("getatr failed (%s)\n", nt_errstr(status));
4223                 correct = False;
4224         }
4225
4226         if (labs(t - time(NULL)) > 60*60*24*10) {
4227                 printf("ERROR: SMBgetatr bug. time is %s",
4228                        ctime(&t));
4229                 t = time(NULL);
4230                 correct = True;
4231         }
4232
4233         t2 = t-60*60*24; /* 1 day ago */
4234
4235         /* Ensure we can't set with out-of-range (unknown) attribute. */
4236         status = cli_setatr(cli, fname, 0x20000, t2);
4237         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4238                 correct = false;
4239                 goto out;
4240         }
4241
4242         status = cli_setatr(cli, fname, 0, t2);
4243         if (!NT_STATUS_IS_OK(status)) {
4244                 printf("setatr failed (%s)\n", nt_errstr(status));
4245                 correct = True;
4246         }
4247
4248         status = cli_getatr(cli, fname, NULL, NULL, &t);
4249         if (!NT_STATUS_IS_OK(status)) {
4250                 printf("getatr failed (%s)\n", nt_errstr(status));
4251                 correct = True;
4252         }
4253
4254         if (t != t2) {
4255                 printf("ERROR: getatr/setatr bug. times are\n%s",
4256                        ctime(&t));
4257                 printf("%s", ctime(&t2));
4258                 correct = True;
4259         }
4260
4261         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4262
4263         /* Check cli_setpathinfo_ext() */
4264         /* Re-create the file. */
4265         status = cli_openx(cli, fname,
4266                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4267         if (!NT_STATUS_IS_OK(status)) {
4268                 printf("Failed to recreate %s (%s)\n",
4269                         fname, nt_errstr(status));
4270                 correct = false;
4271         }
4272         cli_close(cli, fnum);
4273
4274         status = cli_setpathinfo_ext(
4275                 cli,
4276                 fname,
4277                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4278                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4279                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4280                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4281                 FILE_ATTRIBUTE_SYSTEM |
4282                 FILE_ATTRIBUTE_HIDDEN |
4283                 FILE_ATTRIBUTE_READONLY);
4284         if (!NT_STATUS_IS_OK(status)) {
4285                 printf("cli_setpathinfo_ext failed with %s\n",
4286                         nt_errstr(status));
4287                 correct = false;
4288         }
4289
4290         /* Check attributes are correct. */
4291         correct = check_attributes(cli,
4292                         fname,
4293                         FILE_ATTRIBUTE_SYSTEM |
4294                         FILE_ATTRIBUTE_HIDDEN |
4295                         FILE_ATTRIBUTE_READONLY);
4296         if (correct == false) {
4297                 goto out;
4298         }
4299
4300         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4301         status = cli_setpathinfo_ext(
4302                 cli,
4303                 fname,
4304                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4305                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4306                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4307                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4308                 FILE_ATTRIBUTE_NORMAL);
4309         if (!NT_STATUS_IS_OK(status)) {
4310                 printf("cli_setpathinfo_ext failed with %s\n",
4311                         nt_errstr(status));
4312                 correct = false;
4313         }
4314
4315         /* Check attributes are correct. */
4316         correct = check_attributes(cli,
4317                         fname,
4318                         FILE_ATTRIBUTE_SYSTEM |
4319                         FILE_ATTRIBUTE_HIDDEN |
4320                         FILE_ATTRIBUTE_READONLY);
4321         if (correct == false) {
4322                 goto out;
4323         }
4324
4325         /* Setting to (uint16_t)-1 should also be ignored. */
4326         status = cli_setpathinfo_ext(
4327                 cli,
4328                 fname,
4329                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4330                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4331                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4332                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4333                 (uint32_t)-1);
4334         if (!NT_STATUS_IS_OK(status)) {
4335                 printf("cli_setpathinfo_ext failed with %s\n",
4336                         nt_errstr(status));
4337                 correct = false;
4338         }
4339
4340         /* Check attributes are correct. */
4341         correct = check_attributes(cli,
4342                         fname,
4343                         FILE_ATTRIBUTE_SYSTEM |
4344                         FILE_ATTRIBUTE_HIDDEN |
4345                         FILE_ATTRIBUTE_READONLY);
4346         if (correct == false) {
4347                 goto out;
4348         }
4349
4350         /* Setting to 0 should clear them all. */
4351         status = cli_setpathinfo_ext(
4352                 cli,
4353                 fname,
4354                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4355                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4356                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4357                 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4358                 0);
4359         if (!NT_STATUS_IS_OK(status)) {
4360                 printf("cli_setpathinfo_ext failed with %s\n",
4361                         nt_errstr(status));
4362                 correct = false;
4363         }
4364
4365         /* Check attributes are correct. */
4366         correct = check_attributes(cli,
4367                         fname,
4368                         FILE_ATTRIBUTE_NORMAL);
4369         if (correct == false) {
4370                 goto out;
4371         }
4372
4373   out:
4374
4375         cli_unlink(cli,
4376                 fname,
4377                 FILE_ATTRIBUTE_SYSTEM |
4378                 FILE_ATTRIBUTE_HIDDEN|
4379                 FILE_ATTRIBUTE_READONLY);
4380
4381         if (!torture_close_connection(cli)) {
4382                 correct = False;
4383         }
4384
4385         printf("attrib test finished\n");
4386
4387         return correct;
4388 }
4389
4390 static NTSTATUS cli_qfilename(
4391         struct cli_state *cli,
4392         uint16_t fnum,
4393         TALLOC_CTX *mem_ctx,
4394         char **_name)
4395 {
4396         uint16_t recv_flags2;
4397         uint8_t *rdata;
4398         uint32_t num_rdata;
4399         NTSTATUS status;
4400         char *name = NULL;
4401         uint32_t namelen;
4402
4403         status = cli_qfileinfo(talloc_tos(), cli, fnum,
4404                                SMB_QUERY_FILE_NAME_INFO,
4405                                4, CLI_BUFFER_SIZE, &recv_flags2,
4406                                &rdata, &num_rdata);
4407         if (!NT_STATUS_IS_OK(status)) {
4408                 return status;
4409         }
4410
4411         namelen = IVAL(rdata, 0);
4412         if (namelen > (num_rdata - 4)) {
4413                 TALLOC_FREE(rdata);
4414                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4415         }
4416
4417         pull_string_talloc(mem_ctx,
4418                            (const char *)rdata,
4419                            recv_flags2,
4420                            &name,
4421                            rdata + 4,
4422                            namelen,
4423                            STR_UNICODE);
4424         if (name == NULL) {
4425                 status = map_nt_error_from_unix(errno);
4426                 TALLOC_FREE(rdata);
4427                 return status;
4428         }
4429
4430         *_name = name;
4431         TALLOC_FREE(rdata);
4432         return NT_STATUS_OK;
4433 }
4434
4435 /*
4436   This checks a couple of trans2 calls
4437 */
4438 static bool run_trans2test(int dummy)
4439 {
4440         struct cli_state *cli;
4441         uint16_t fnum;
4442         off_t size;
4443         time_t c_time, a_time, m_time;
4444         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4445         const char *fname = "\\trans2.tst";
4446         const char *dname = "\\trans2";
4447         const char *fname2 = "\\trans2\\trans2.tst";
4448         char *pname = NULL;
4449         bool correct = True;
4450         NTSTATUS status;
4451         uint32_t fs_attr;
4452         uint64_t ino;
4453
4454         printf("starting trans2 test\n");
4455
4456         if (!torture_open_connection(&cli, 0)) {
4457                 return False;
4458         }
4459
4460         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4461                 /* Ensure ino is zero, SMB2 gets a real one. */
4462                 ino = 0;
4463         } else {
4464                 /* Ensure ino is -1, SMB1 never gets a real one. */
4465                 ino = (uint64_t)-1;
4466         }
4467
4468         status = cli_get_fs_attr_info(cli, &fs_attr);
4469         if (!NT_STATUS_IS_OK(status)) {
4470                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4471                        nt_errstr(status));
4472                 correct = false;
4473         }
4474
4475         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4476         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4477         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4478                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4479         if (!NT_STATUS_IS_OK(status)) {
4480                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4481                 correct = False;
4482         }
4483
4484         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4485         if (!NT_STATUS_IS_OK(status)) {
4486                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4487                 correct = False;
4488         }
4489         else if (strcmp(pname, fname)) {
4490                 printf("qfilename gave different name? [%s] [%s]\n",
4491                        fname, pname);
4492                 correct = False;
4493         }
4494
4495         cli_close(cli, fnum);
4496
4497         sleep(2);
4498
4499         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4500         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4501                           &fnum);
4502         if (!NT_STATUS_IS_OK(status)) {
4503                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4504                 return False;
4505         }
4506         cli_close(cli, fnum);
4507
4508         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4509                                 NULL);
4510         if (!NT_STATUS_IS_OK(status)) {
4511                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4512                 correct = False;
4513         } else {
4514                 time_t t = time(NULL);
4515
4516                 if (c_time != m_time) {
4517                         printf("create time=%s", ctime(&c_time));
4518                         printf("modify time=%s", ctime(&m_time));
4519                         printf("This system appears to have sticky create times\n");
4520                 }
4521                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4522                         printf("access time=%s", ctime(&a_time));
4523                         printf("This system appears to set a midnight access time\n");
4524                         correct = False;
4525                 }
4526
4527                 if (labs(m_time - t) > 60*60*24*7) {
4528                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4529                         correct = False;
4530                 }
4531         }
4532
4533
4534         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4535         cli_openx(cli, fname, 
4536                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4537         cli_close(cli, fnum);
4538         status = cli_qpathinfo2(cli,
4539                                 fname,
4540                                 &c_time_ts,
4541                                 &a_time_ts,
4542                                 &w_time_ts,
4543                                 &m_time_ts,
4544                                 &size,
4545                                 NULL,
4546                                 &ino,
4547                                 NULL);
4548         if (!NT_STATUS_IS_OK(status)) {
4549                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4550                 correct = False;
4551         } else {
4552                 if (w_time_ts.tv_sec < 60*60*24*2) {
4553                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
4554                         printf("This system appears to set a initial 0 write time\n");
4555                         correct = False;
4556                 }
4557                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4558                         /* SMB2 should always return an inode. */
4559                         if (ino == 0) {
4560                                 printf("SMB2 bad inode (0)\n");
4561                                 correct = false;
4562                         }
4563                 } else {
4564                         /* SMB1 must always return zero here. */
4565                         if (ino != 0) {
4566                                 printf("SMB1 bad inode (!0)\n");
4567                                 correct = false;
4568                         }
4569                 }
4570         }
4571
4572         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4573
4574
4575         /* check if the server updates the directory modification time
4576            when creating a new file */
4577         status = cli_mkdir(cli, dname);
4578         if (!NT_STATUS_IS_OK(status)) {
4579                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4580                 correct = False;
4581         }
4582         sleep(3);
4583         status = cli_qpathinfo2(cli,
4584                                 "\\trans2\\",
4585                                 &c_time_ts,
4586                                 &a_time_ts,
4587                                 &w_time_ts,
4588                                 &m_time_ts,
4589                                 &size,
4590                                 NULL,
4591                                 NULL,
4592                                 NULL);
4593         if (!NT_STATUS_IS_OK(status)) {
4594                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4595                 correct = False;
4596         }
4597
4598         cli_openx(cli, fname2, 
4599                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4600         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4601         cli_close(cli, fnum);
4602         status = cli_qpathinfo2(cli,
4603                                 "\\trans2\\",
4604                                 &c_time_ts,
4605                                 &a_time_ts,
4606                                 &w_time_ts,
4607                                 &m_time2_ts,
4608                                 &size,
4609                                 NULL,
4610                                 NULL,
4611                                 NULL);
4612         if (!NT_STATUS_IS_OK(status)) {
4613                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4614                 correct = False;
4615         } else {
4616                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4617                     == 0) {
4618                         printf("This system does not update directory modification times\n");
4619                         correct = False;
4620                 }
4621         }
4622         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4623         cli_rmdir(cli, dname);
4624
4625         if (!torture_close_connection(cli)) {
4626                 correct = False;
4627         }
4628
4629         printf("trans2 test finished\n");
4630
4631         return correct;
4632 }
4633
4634 /*
4635   This checks new W2K calls.
4636 */
4637
4638 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4639 {
4640         uint8_t *buf = NULL;
4641         uint32_t len;
4642         NTSTATUS status;
4643
4644         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4645                                CLI_BUFFER_SIZE, NULL, &buf, &len);
4646         if (!NT_STATUS_IS_OK(status)) {
4647                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4648                        nt_errstr(status));
4649         } else {
4650                 printf("qfileinfo: level %d, len = %u\n", level, len);
4651                 dump_data(0, (uint8_t *)buf, len);
4652                 printf("\n");
4653         }
4654         TALLOC_FREE(buf);
4655         return status;
4656 }
4657
4658 static bool run_w2ktest(int dummy)
4659 {
4660         struct cli_state *cli;
4661         uint16_t fnum;
4662         const char *fname = "\\w2ktest\\w2k.tst";
4663         int level;
4664         bool correct = True;
4665
4666         printf("starting w2k test\n");
4667
4668         if (!torture_open_connection(&cli, 0)) {
4669                 return False;
4670         }
4671
4672         cli_openx(cli, fname, 
4673                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
4674
4675         for (level = 1004; level < 1040; level++) {
4676                 new_trans(cli, fnum, level);
4677         }
4678
4679         cli_close(cli, fnum);
4680
4681         if (!torture_close_connection(cli)) {
4682                 correct = False;
4683         }
4684
4685         printf("w2k test finished\n");
4686
4687         return correct;
4688 }
4689
4690
4691 /*
4692   this is a harness for some oplock tests
4693  */
4694 static bool run_oplock1(int dummy)
4695 {
4696         struct cli_state *cli1;
4697         const char *fname = "\\lockt1.lck";
4698         uint16_t fnum1;
4699         bool correct = True;
4700         NTSTATUS status;
4701
4702         printf("starting oplock test 1\n");
4703
4704         if (!torture_open_connection(&cli1, 0)) {
4705                 return False;
4706         }
4707
4708         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4709
4710         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4711
4712         cli1->use_oplocks = True;
4713
4714         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4715                           &fnum1);
4716         if (!NT_STATUS_IS_OK(status)) {
4717                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4718                 return False;
4719         }
4720
4721         cli1->use_oplocks = False;
4722
4723         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4725
4726         status = cli_close(cli1, fnum1);
4727         if (!NT_STATUS_IS_OK(status)) {
4728                 printf("close2 failed (%s)\n", nt_errstr(status));
4729                 return False;
4730         }
4731
4732         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4733         if (!NT_STATUS_IS_OK(status)) {
4734                 printf("unlink failed (%s)\n", nt_errstr(status));
4735                 return False;
4736         }
4737
4738         if (!torture_close_connection(cli1)) {
4739                 correct = False;
4740         }
4741
4742         printf("finished oplock test 1\n");
4743
4744         return correct;
4745 }
4746
4747 static bool run_oplock2(int dummy)
4748 {
4749         struct cli_state *cli1, *cli2;
4750         const char *fname = "\\lockt2.lck";
4751         uint16_t fnum1, fnum2;
4752         int saved_use_oplocks = use_oplocks;
4753         char buf[4];
4754         bool correct = True;
4755         volatile bool *shared_correct;
4756         size_t nread;
4757         NTSTATUS status;
4758
4759         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4760         *shared_correct = True;
4761
4762         use_level_II_oplocks = True;
4763         use_oplocks = True;
4764
4765         printf("starting oplock test 2\n");
4766
4767         if (!torture_open_connection(&cli1, 0)) {
4768                 use_level_II_oplocks = False;
4769                 use_oplocks = saved_use_oplocks;
4770                 return False;
4771         }
4772
4773         if (!torture_open_connection(&cli2, 1)) {
4774                 use_level_II_oplocks = False;
4775                 use_oplocks = saved_use_oplocks;
4776                 return False;
4777         }
4778
4779         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4780
4781         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4782         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4783
4784         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4785                           &fnum1);
4786         if (!NT_STATUS_IS_OK(status)) {
4787                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4788                 return False;
4789         }
4790
4791         /* Don't need the globals any more. */
4792         use_level_II_oplocks = False;
4793         use_oplocks = saved_use_oplocks;
4794
4795         if (fork() == 0) {
4796                 /* Child code */
4797                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4798                 if (!NT_STATUS_IS_OK(status)) {
4799                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4800                         *shared_correct = False;
4801                         exit(0);
4802                 }
4803
4804                 sleep(2);
4805
4806                 status = cli_close(cli2, fnum2);
4807                 if (!NT_STATUS_IS_OK(status)) {
4808                         printf("close2 failed (%s)\n", nt_errstr(status));
4809                         *shared_correct = False;
4810                 }
4811
4812                 exit(0);
4813         }
4814
4815         sleep(2);
4816
4817         /* Ensure cli1 processes the break. Empty file should always return 0
4818          * bytes.  */
4819         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4820         if (!NT_STATUS_IS_OK(status)) {
4821                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4822                 correct = false;
4823         } else if (nread != 0) {
4824                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4825                       (unsigned long)nread, 0);
4826                 correct = false;
4827         }
4828
4829         /* Should now be at level II. */
4830         /* Test if sending a write locks causes a break to none. */
4831         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4832         if (!NT_STATUS_IS_OK(status)) {
4833                 printf("lock failed (%s)\n", nt_errstr(status));
4834                 correct = False;
4835         }
4836
4837         cli_unlock(cli1, fnum1, 0, 4);
4838
4839         sleep(2);
4840
4841         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4842         if (!NT_STATUS_IS_OK(status)) {
4843                 printf("lock failed (%s)\n", nt_errstr(status));
4844                 correct = False;
4845         }
4846
4847         cli_unlock(cli1, fnum1, 0, 4);
4848
4849         sleep(2);
4850
4851         cli_read(cli1, fnum1, buf, 0, 4, NULL);
4852
4853         status = cli_close(cli1, fnum1);
4854         if (!NT_STATUS_IS_OK(status)) {
4855                 printf("close1 failed (%s)\n", nt_errstr(status));
4856                 correct = False;
4857         }
4858
4859         sleep(4);
4860
4861         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4862         if (!NT_STATUS_IS_OK(status)) {
4863                 printf("unlink failed (%s)\n", nt_errstr(status));
4864                 correct = False;
4865         }
4866
4867         if (!torture_close_connection(cli1)) {
4868                 correct = False;
4869         }
4870
4871         if (!*shared_correct) {
4872                 correct = False;
4873         }
4874
4875         printf("finished oplock test 2\n");
4876
4877         return correct;
4878 }
4879
4880 struct oplock4_state {
4881         struct tevent_context *ev;
4882         struct cli_state *cli;
4883         bool *got_break;
4884         uint16_t *fnum2;
4885 };
4886
4887 static void oplock4_got_break(struct tevent_req *req);
4888 static void oplock4_got_open(struct tevent_req *req);
4889
4890 static bool run_oplock4(int dummy)
4891 {
4892         struct tevent_context *ev;
4893         struct cli_state *cli1, *cli2;
4894         struct tevent_req *oplock_req, *open_req;
4895         const char *fname = "\\lockt4.lck";
4896         const char *fname_ln = "\\lockt4_ln.lck";
4897         uint16_t fnum1, fnum2;
4898         int saved_use_oplocks = use_oplocks;
4899         NTSTATUS status;
4900         bool correct = true;
4901
4902         bool got_break;
4903
4904         struct oplock4_state *state;
4905
4906         printf("starting oplock test 4\n");
4907
4908         if (!torture_open_connection(&cli1, 0)) {
4909                 use_level_II_oplocks = false;
4910                 use_oplocks = saved_use_oplocks;
4911                 return false;
4912         }
4913
4914         if (!torture_open_connection(&cli2, 1)) {
4915                 use_level_II_oplocks = false;
4916                 use_oplocks = saved_use_oplocks;
4917                 return false;
4918         }
4919
4920         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4921         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4922
4923         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4924         smbXcli_conn_set_sockopt(cli2->conn, sockops);
4925
4926         /* Create the file. */
4927         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4928                           &fnum1);
4929         if (!NT_STATUS_IS_OK(status)) {
4930                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4931                 return false;
4932         }
4933
4934         status = cli_close(cli1, fnum1);
4935         if (!NT_STATUS_IS_OK(status)) {
4936                 printf("close1 failed (%s)\n", nt_errstr(status));
4937                 return false;
4938         }
4939
4940         /* Now create a hardlink. */
4941         status = cli_hardlink(cli1, fname, fname_ln);
4942         if (!NT_STATUS_IS_OK(status)) {
4943                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4944                 return false;
4945         }
4946
4947         /* Prove that opening hardlinks cause deny modes to conflict. */
4948         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4949         if (!NT_STATUS_IS_OK(status)) {
4950                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4951                 return false;
4952         }
4953
4954         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4955         if (NT_STATUS_IS_OK(status)) {
4956                 printf("open of %s succeeded - should fail with sharing violation.\n",
4957                         fname_ln);
4958                 return false;
4959         }
4960
4961         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4962                 printf("open of %s should fail with sharing violation. Got %s\n",
4963                         fname_ln, nt_errstr(status));
4964                 return false;
4965         }
4966
4967         status = cli_close(cli1, fnum1);
4968         if (!NT_STATUS_IS_OK(status)) {
4969                 printf("close1 failed (%s)\n", nt_errstr(status));
4970                 return false;
4971         }
4972
4973         cli1->use_oplocks = true;
4974         cli2->use_oplocks = true;
4975
4976         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4977         if (!NT_STATUS_IS_OK(status)) {
4978                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4979                 return false;
4980         }
4981
4982         ev = samba_tevent_context_init(talloc_tos());
4983         if (ev == NULL) {
4984                 printf("tevent_context_init failed\n");
4985                 return false;
4986         }
4987
4988         state = talloc(ev, struct oplock4_state);
4989         if (state == NULL) {
4990                 printf("talloc failed\n");
4991                 return false;
4992         }
4993         state->ev = ev;
4994         state->cli = cli1;
4995         state->got_break = &got_break;
4996         state->fnum2 = &fnum2;
4997
4998         oplock_req = cli_smb_oplock_break_waiter_send(
4999                 talloc_tos(), ev, cli1);
5000         if (oplock_req == NULL) {
5001                 printf("cli_smb_oplock_break_waiter_send failed\n");
5002                 return false;
5003         }
5004         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5005
5006         open_req = cli_openx_send(
5007                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5008         if (open_req == NULL) {
5009                 printf("cli_openx_send failed\n");
5010                 return false;
5011         }
5012         tevent_req_set_callback(open_req, oplock4_got_open, state);
5013
5014         got_break = false;
5015         fnum2 = 0xffff;
5016
5017         while (!got_break || fnum2 == 0xffff) {
5018                 int ret;
5019                 ret = tevent_loop_once(ev);
5020                 if (ret == -1) {
5021                         printf("tevent_loop_once failed: %s\n",
5022                                strerror(errno));
5023                         return false;
5024                 }
5025         }
5026
5027         status = cli_close(cli2, fnum2);
5028         if (!NT_STATUS_IS_OK(status)) {
5029                 printf("close2 failed (%s)\n", nt_errstr(status));
5030                 correct = false;
5031         }
5032
5033         status = cli_close(cli1, fnum1);
5034         if (!NT_STATUS_IS_OK(status)) {
5035                 printf("close1 failed (%s)\n", nt_errstr(status));
5036                 correct = false;
5037         }
5038
5039         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5040         if (!NT_STATUS_IS_OK(status)) {
5041                 printf("unlink failed (%s)\n", nt_errstr(status));
5042                 correct = false;
5043         }
5044
5045         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5046         if (!NT_STATUS_IS_OK(status)) {
5047                 printf("unlink failed (%s)\n", nt_errstr(status));
5048                 correct = false;
5049         }
5050
5051         if (!torture_close_connection(cli1)) {
5052                 correct = false;
5053         }
5054
5055         if (!got_break) {
5056                 correct = false;
5057         }
5058
5059         printf("finished oplock test 4\n");
5060
5061         return correct;
5062 }
5063
5064 static void oplock4_got_break(struct tevent_req *req)
5065 {
5066         struct oplock4_state *state = tevent_req_callback_data(
5067                 req, struct oplock4_state);
5068         uint16_t fnum;
5069         uint8_t level;
5070         NTSTATUS status;
5071
5072         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5073         TALLOC_FREE(req);
5074         if (!NT_STATUS_IS_OK(status)) {
5075                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5076                        nt_errstr(status));
5077                 return;
5078         }
5079         *state->got_break = true;
5080
5081         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5082                                   NO_OPLOCK);
5083         if (req == NULL) {
5084                 printf("cli_oplock_ack_send failed\n");
5085                 return;
5086         }
5087 }
5088
5089 static void oplock4_got_open(struct tevent_req *req)
5090 {
5091         struct oplock4_state *state = tevent_req_callback_data(
5092                 req, struct oplock4_state);
5093         NTSTATUS status;
5094
5095         status = cli_openx_recv(req, state->fnum2);
5096         if (!NT_STATUS_IS_OK(status)) {
5097                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5098                 *state->fnum2 = 0xffff;
5099         }
5100 }
5101
5102 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5103
5104 struct oplock5_state {
5105         int pipe_down_fd;
5106 };
5107
5108 /*
5109  * Async open the file that has a kernel oplock, do an echo to get
5110  * that 100% across, close the file to signal to the child fd that the
5111  * oplock can be dropped, wait for the open reply.
5112  */
5113
5114 static void oplock5_opened(struct tevent_req *subreq);
5115 static void oplock5_pong(struct tevent_req *subreq);
5116 static void oplock5_timedout(struct tevent_req *subreq);
5117
5118 static struct tevent_req *oplock5_send(
5119         TALLOC_CTX *mem_ctx,
5120         struct tevent_context *ev,
5121         struct cli_state *cli,
5122         const char *fname,
5123         int pipe_down_fd)
5124 {
5125         struct tevent_req *req = NULL, *subreq = NULL;
5126         struct oplock5_state *state = NULL;
5127         static uint8_t data = 0;
5128
5129         req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5130         if (req == NULL) {
5131                 return NULL;
5132         }
5133         state->pipe_down_fd = pipe_down_fd;
5134
5135         subreq = cli_ntcreate_send(
5136                 state,
5137                 ev,
5138                 cli,
5139                 fname,
5140                 0,                      /* CreatFlags */
5141                 SEC_FILE_READ_DATA,    /* DesiredAccess */
5142                 FILE_ATTRIBUTE_NORMAL,  /* FileAttributes */
5143                 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5144                 FILE_OPEN,               /* CreateDisposition */
5145                 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5146                 0,                       /* Impersonation */
5147                 0);                      /* SecurityFlags */
5148         if (tevent_req_nomem(subreq, req)) {
5149                 return tevent_req_post(req, ev);
5150         }
5151         tevent_req_set_callback(subreq, oplock5_opened, req);
5152
5153         subreq = cli_echo_send(
5154                 state,
5155                 ev,
5156                 cli,
5157                 1,
5158                 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5159         if (tevent_req_nomem(subreq, req)) {
5160                 return tevent_req_post(req, ev);
5161         }
5162         tevent_req_set_callback(subreq, oplock5_pong, req);
5163
5164         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5165         if (tevent_req_nomem(subreq, req)) {
5166                 return tevent_req_post(req, ev);
5167         }
5168         tevent_req_set_callback(subreq, oplock5_timedout, req);
5169
5170         return req;
5171 }
5172
5173 static void oplock5_opened(struct tevent_req *subreq)
5174 {
5175         struct tevent_req *req = tevent_req_callback_data(
5176                 subreq, struct tevent_req);
5177         NTSTATUS status;
5178         uint16_t fnum;
5179
5180         status = cli_ntcreate_recv(subreq, &fnum, NULL);
5181         TALLOC_FREE(subreq);
5182         if (tevent_req_nterror(req, status)) {
5183                 return;
5184         }
5185         tevent_req_done(req);
5186 }
5187
5188 static void oplock5_pong(struct tevent_req *subreq)
5189 {
5190         struct tevent_req *req = tevent_req_callback_data(
5191                 subreq, struct tevent_req);
5192         struct oplock5_state *state = tevent_req_data(
5193                 req, struct oplock5_state);
5194         NTSTATUS status;
5195
5196         status = cli_echo_recv(subreq);
5197         TALLOC_FREE(subreq);
5198         if (tevent_req_nterror(req, status)) {
5199                 return;
5200         }
5201
5202         close(state->pipe_down_fd);
5203 }
5204
5205 static void oplock5_timedout(struct tevent_req *subreq)
5206 {
5207         struct tevent_req *req = tevent_req_callback_data(
5208                 subreq, struct tevent_req);
5209         bool ok;
5210
5211         ok = tevent_wakeup_recv(subreq);
5212         TALLOC_FREE(subreq);
5213         if (!ok) {
5214                 tevent_req_oom(req);
5215                 return;
5216         }
5217         tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5218 }
5219
5220 static NTSTATUS oplock5_recv(struct tevent_req *req)
5221 {
5222         return tevent_req_simple_recv_ntstatus(req);
5223 }
5224
5225 static bool run_oplock5(int dummy)
5226 {
5227         struct tevent_context *ev = NULL;
5228         struct tevent_req *req = NULL;
5229         struct cli_state *cli = NULL;
5230         const char *fname = "oplock5.txt";
5231         int pipe_down[2], pipe_up[2];
5232         pid_t child_pid;
5233         uint8_t c = '\0';
5234         NTSTATUS status;
5235         int ret;
5236         bool ok;
5237
5238         printf("starting oplock5\n");
5239
5240         if (local_path == NULL) {
5241                 d_fprintf(stderr, "oplock5 must be given a local path via "
5242                           "-l <localpath>\n");
5243                 return false;
5244         }
5245
5246         ret = pipe(pipe_down);
5247         if (ret == -1) {
5248                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5249                 return false;
5250         }
5251         ret = pipe(pipe_up);
5252         if (ret == -1) {
5253                 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5254                 return false;
5255         }
5256
5257         child_pid = fork();
5258         if (child_pid == -1) {
5259                 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5260                 return false;
5261         }
5262
5263         if (child_pid == 0) {
5264                 char *local_file = NULL;
5265                 int fd;
5266
5267                 close(pipe_down[1]);
5268                 close(pipe_up[0]);
5269
5270                 local_file = talloc_asprintf(
5271                         talloc_tos(), "%s/%s", local_path, fname);
5272                 if (local_file == 0) {
5273                         c = 1;
5274                         goto do_write;
5275                 }
5276                 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5277                 if (fd == -1) {
5278                         d_fprintf(stderr,
5279                                   "open(%s) in child failed: %s\n",
5280                                   local_file,
5281                                   strerror(errno));
5282                         c = 2;
5283                         goto do_write;
5284                 }
5285
5286                 signal(SIGIO, SIG_IGN);
5287
5288                 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5289                 if (ret == -1) {
5290                         d_fprintf(stderr,
5291                                   "SETLEASE in child failed: %s\n",
5292                                   strerror(errno));
5293                         c = 3;
5294                         goto do_write;
5295                 }
5296
5297         do_write:
5298                 ret = sys_write(pipe_up[1], &c, sizeof(c));
5299                 if (ret == -1) {
5300                         d_fprintf(stderr,
5301                                   "sys_write failed: %s\n",
5302                                   strerror(errno));
5303                         exit(4);
5304                 }
5305                 ret = sys_read(pipe_down[0], &c, sizeof(c));
5306                 if (ret == -1) {
5307                         d_fprintf(stderr,
5308                                   "sys_read failed: %s\n",
5309                                   strerror(errno));
5310                         exit(5);
5311                 }
5312                 exit(0);
5313         }
5314
5315         close(pipe_up[1]);
5316         close(pipe_down[0]);
5317
5318         ret = sys_read(pipe_up[0], &c, sizeof(c));
5319         if (ret != 1) {
5320                 d_fprintf(stderr,
5321                           "sys_read failed: %s\n",
5322                           strerror(errno));
5323                 return false;
5324         }
5325         if (c != 0) {
5326                 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5327                 return false;
5328         }
5329
5330         ok = torture_open_connection(&cli, 0);
5331         if (!ok) {
5332                 d_fprintf(stderr, "torture_open_connection failed\n");
5333                 return false;
5334         }
5335
5336         ev = samba_tevent_context_init(talloc_tos());
5337         if (ev == NULL) {
5338                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5339                 return false;
5340         }
5341
5342         req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5343         if (req == NULL) {
5344                 d_fprintf(stderr, "oplock5_send failed\n");
5345                 return false;
5346         }
5347
5348         ok = tevent_req_poll_ntstatus(req, ev, &status);
5349         if (!ok) {
5350                 d_fprintf(stderr,
5351                           "tevent_req_poll_ntstatus failed: %s\n",
5352                           nt_errstr(status));
5353                 return false;
5354         }
5355
5356         status = oplock5_recv(req);
5357         TALLOC_FREE(req);
5358         if (!NT_STATUS_IS_OK(status)) {
5359                 d_fprintf(stderr,
5360                           "oplock5 failed: %s\n",
5361                           nt_errstr(status));
5362                 return false;
5363         }
5364
5365         return true;
5366 }
5367
5368 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5369
5370 /*
5371   Test delete on close semantics.
5372  */
5373 static bool run_deletetest(int dummy)
5374 {
5375         struct cli_state *cli1 = NULL;
5376         struct cli_state *cli2 = NULL;
5377         const char *fname = "\\delete.file";
5378         uint16_t fnum1 = (uint16_t)-1;
5379         uint16_t fnum2 = (uint16_t)-1;
5380         bool correct = false;
5381         NTSTATUS status;
5382
5383         printf("starting delete test\n");
5384
5385         if (!torture_open_connection(&cli1, 0)) {
5386                 return False;
5387         }
5388
5389         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5390
5391         /* Test 1 - this should delete the file on close. */
5392
5393         cli_setatr(cli1, fname, 0, 0);
5394         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5395
5396         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5397                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5398                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5399         if (!NT_STATUS_IS_OK(status)) {
5400                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5401                 goto fail;
5402         }
5403
5404         status = cli_close(cli1, fnum1);
5405         if (!NT_STATUS_IS_OK(status)) {
5406                 printf("[1] close failed (%s)\n", nt_errstr(status));
5407                 goto fail;
5408         }
5409
5410         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5411         if (NT_STATUS_IS_OK(status)) {
5412                 printf("[1] open of %s succeeded (should fail)\n", fname);
5413                 goto fail;
5414         }
5415
5416         printf("first delete on close test succeeded.\n");
5417
5418         /* Test 2 - this should delete the file on close. */
5419
5420         cli_setatr(cli1, fname, 0, 0);
5421         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5422
5423         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5424                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5425                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5426         if (!NT_STATUS_IS_OK(status)) {
5427                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5428                 goto fail;
5429         }
5430
5431         status = cli_nt_delete_on_close(cli1, fnum1, true);
5432         if (!NT_STATUS_IS_OK(status)) {
5433                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5434                 goto fail;
5435         }
5436
5437         status = cli_close(cli1, fnum1);
5438         if (!NT_STATUS_IS_OK(status)) {
5439                 printf("[2] close failed (%s)\n", nt_errstr(status));
5440                 goto fail;
5441         }
5442
5443         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5444         if (NT_STATUS_IS_OK(status)) {
5445                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5446                 status = cli_close(cli1, fnum1);
5447                 if (!NT_STATUS_IS_OK(status)) {
5448                         printf("[2] close failed (%s)\n", nt_errstr(status));
5449                 }
5450                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5451                 goto fail;
5452         }
5453
5454         printf("second delete on close test succeeded.\n");
5455
5456         /* Test 3 - ... */
5457         cli_setatr(cli1, fname, 0, 0);
5458         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5459
5460         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5461                               FILE_ATTRIBUTE_NORMAL,
5462                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5463                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5464         if (!NT_STATUS_IS_OK(status)) {
5465                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5466                 goto fail;
5467         }
5468
5469         /* This should fail with a sharing violation - open for delete is only compatible
5470            with SHARE_DELETE. */
5471
5472         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5473                               FILE_ATTRIBUTE_NORMAL,
5474                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5475                               FILE_OPEN, 0, 0, &fnum2, NULL);
5476         if (NT_STATUS_IS_OK(status)) {
5477                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
5478                 goto fail;
5479         }
5480
5481         /* This should succeed. */
5482         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5483                              FILE_ATTRIBUTE_NORMAL,
5484                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5485                              FILE_OPEN, 0, 0, &fnum2, NULL);
5486         if (!NT_STATUS_IS_OK(status)) {
5487                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5488                 goto fail;
5489         }
5490
5491         status = cli_nt_delete_on_close(cli1, fnum1, true);
5492         if (!NT_STATUS_IS_OK(status)) {
5493                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5494                 goto fail;
5495         }
5496
5497         status = cli_close(cli1, fnum1);
5498         if (!NT_STATUS_IS_OK(status)) {
5499                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5500                 goto fail;
5501         }
5502
5503         status = cli_close(cli1, fnum2);
5504         if (!NT_STATUS_IS_OK(status)) {
5505                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5506                 goto fail;
5507         }
5508
5509         /* This should fail - file should no longer be there. */
5510
5511         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5512         if (NT_STATUS_IS_OK(status)) {
5513                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5514                 status = cli_close(cli1, fnum1);
5515                 if (!NT_STATUS_IS_OK(status)) {
5516                         printf("[3] close failed (%s)\n", nt_errstr(status));
5517                 }
5518                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5519                 goto fail;
5520         }
5521
5522         printf("third delete on close test succeeded.\n");
5523
5524         /* Test 4 ... */
5525         cli_setatr(cli1, fname, 0, 0);
5526         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5527
5528         status = cli_ntcreate(cli1, fname, 0,
5529                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5530                               FILE_ATTRIBUTE_NORMAL,
5531                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5532                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5533         if (!NT_STATUS_IS_OK(status)) {
5534                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5535                 goto fail;
5536         }
5537
5538         /* This should succeed. */
5539         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5540                              FILE_ATTRIBUTE_NORMAL,
5541                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5542                              FILE_OPEN, 0, 0, &fnum2, NULL);
5543         if (!NT_STATUS_IS_OK(status)) {
5544                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5545                 goto fail;
5546         }
5547
5548         status = cli_close(cli1, fnum2);
5549         if (!NT_STATUS_IS_OK(status)) {
5550                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5551                 goto fail;
5552         }
5553
5554         status = cli_nt_delete_on_close(cli1, fnum1, true);
5555         if (!NT_STATUS_IS_OK(status)) {
5556                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5557                 goto fail;
5558         }
5559
5560         /* This should fail - no more opens once delete on close set. */
5561         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5562                               FILE_ATTRIBUTE_NORMAL,
5563                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5564                               FILE_OPEN, 0, 0, &fnum2, NULL);
5565         if (NT_STATUS_IS_OK(status)) {
5566                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
5567                 goto fail;
5568         }
5569
5570         status = cli_close(cli1, fnum1);
5571         if (!NT_STATUS_IS_OK(status)) {
5572                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5573                 goto fail;
5574         }
5575
5576         printf("fourth delete on close test succeeded.\n");
5577
5578         /* Test 5 ... */
5579         cli_setatr(cli1, fname, 0, 0);
5580         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5581
5582         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5583         if (!NT_STATUS_IS_OK(status)) {
5584                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5585                 goto fail;
5586         }
5587
5588         /* This should fail - only allowed on NT opens with DELETE access. */
5589
5590         status = cli_nt_delete_on_close(cli1, fnum1, true);
5591         if (NT_STATUS_IS_OK(status)) {
5592                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5593                 goto fail;
5594         }
5595
5596         status = cli_close(cli1, fnum1);
5597         if (!NT_STATUS_IS_OK(status)) {
5598                 printf("[5] close failed (%s)\n", nt_errstr(status));
5599                 goto fail;
5600         }
5601
5602         printf("fifth delete on close test succeeded.\n");
5603
5604         /* Test 6 ... */
5605         cli_setatr(cli1, fname, 0, 0);
5606         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5607
5608         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5609                              FILE_ATTRIBUTE_NORMAL,
5610                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5611                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5612         if (!NT_STATUS_IS_OK(status)) {
5613                 printf("[6] open of %s failed (%s)\n", fname,
5614                        nt_errstr(status));
5615                 goto fail;
5616         }
5617
5618         /* This should fail - only allowed on NT opens with DELETE access. */
5619
5620         status = cli_nt_delete_on_close(cli1, fnum1, true);
5621         if (NT_STATUS_IS_OK(status)) {
5622                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5623                 goto fail;
5624         }
5625
5626         status = cli_close(cli1, fnum1);
5627         if (!NT_STATUS_IS_OK(status)) {
5628                 printf("[6] close failed (%s)\n", nt_errstr(status));
5629                 goto fail;
5630         }
5631
5632         printf("sixth delete on close test succeeded.\n");
5633
5634         /* Test 7 ... */
5635         cli_setatr(cli1, fname, 0, 0);
5636         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5637
5638         status = cli_ntcreate(cli1, fname, 0,
5639                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5640                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5641                               0, 0, &fnum1, NULL);
5642         if (!NT_STATUS_IS_OK(status)) {
5643                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5644                 goto fail;
5645         }
5646
5647         status = cli_nt_delete_on_close(cli1, fnum1, true);
5648         if (!NT_STATUS_IS_OK(status)) {
5649                 printf("[7] setting delete_on_close on file failed !\n");
5650                 goto fail;
5651         }
5652
5653         status = cli_nt_delete_on_close(cli1, fnum1, false);
5654         if (!NT_STATUS_IS_OK(status)) {
5655                 printf("[7] unsetting delete_on_close on file failed !\n");
5656                 goto fail;
5657         }
5658
5659         status = cli_close(cli1, fnum1);
5660         if (!NT_STATUS_IS_OK(status)) {
5661                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5662                 goto fail;
5663         }
5664
5665         /* This next open should succeed - we reset the flag. */
5666         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5667         if (!NT_STATUS_IS_OK(status)) {
5668                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5669                 goto fail;
5670         }
5671
5672         status = cli_close(cli1, fnum1);
5673         if (!NT_STATUS_IS_OK(status)) {
5674                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5675                 goto fail;
5676         }
5677
5678         printf("seventh delete on close test succeeded.\n");
5679
5680         /* Test 8 ... */
5681         cli_setatr(cli1, fname, 0, 0);
5682         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5683
5684         if (!torture_open_connection(&cli2, 1)) {
5685                 printf("[8] failed to open second connection.\n");
5686                 goto fail;
5687         }
5688
5689         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5690
5691         status = cli_ntcreate(cli1, fname, 0,
5692                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5693                              FILE_ATTRIBUTE_NORMAL,
5694                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5695                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5696         if (!NT_STATUS_IS_OK(status)) {
5697                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5698                 goto fail;
5699         }
5700
5701         status = cli_ntcreate(cli2, fname, 0,
5702                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5703                              FILE_ATTRIBUTE_NORMAL,
5704                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5705                              FILE_OPEN, 0, 0, &fnum2, NULL);
5706         if (!NT_STATUS_IS_OK(status)) {
5707                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5708                 goto fail;
5709         }
5710
5711         status = cli_nt_delete_on_close(cli1, fnum1, true);
5712         if (!NT_STATUS_IS_OK(status)) {
5713                 printf("[8] setting delete_on_close on file failed !\n");
5714                 goto fail;
5715         }
5716
5717         status = cli_close(cli1, fnum1);
5718         if (!NT_STATUS_IS_OK(status)) {
5719                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5720                 goto fail;
5721         }
5722
5723         status = cli_close(cli2, fnum2);
5724         if (!NT_STATUS_IS_OK(status)) {
5725                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5726                 goto fail;
5727         }
5728
5729         /* This should fail.. */
5730         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5731         if (NT_STATUS_IS_OK(status)) {
5732                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5733                 goto fail;
5734         }
5735
5736         printf("eighth delete on close test succeeded.\n");
5737
5738         /* Test 9 ... */
5739
5740         /* This should fail - we need to set DELETE_ACCESS. */
5741         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5742                               FILE_ATTRIBUTE_NORMAL,
5743                               FILE_SHARE_NONE,
5744                               FILE_OVERWRITE_IF,
5745                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5746         if (NT_STATUS_IS_OK(status)) {
5747                 printf("[9] open of %s succeeded should have failed!\n", fname);
5748                 goto fail;
5749         }
5750
5751         printf("ninth delete on close test succeeded.\n");
5752
5753         /* Test 10 ... */
5754
5755         status = cli_ntcreate(cli1, fname, 0,
5756                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5757                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5758                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5759                              0, &fnum1, NULL);
5760         if (!NT_STATUS_IS_OK(status)) {
5761                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5762                 goto fail;
5763         }
5764
5765         /* This should delete the file. */
5766         status = cli_close(cli1, fnum1);
5767         if (!NT_STATUS_IS_OK(status)) {
5768                 printf("[10] close failed (%s)\n", nt_errstr(status));
5769                 goto fail;
5770         }
5771
5772         /* This should fail.. */
5773         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5774         if (NT_STATUS_IS_OK(status)) {
5775                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5776                 goto fail;
5777         }
5778
5779         printf("tenth delete on close test succeeded.\n");
5780
5781         /* Test 11 ... */
5782
5783         cli_setatr(cli1, fname, 0, 0);
5784         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5785
5786         /* Can we open a read-only file with delete access? */
5787
5788         /* Create a readonly file. */
5789         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5790                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5791                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5792         if (!NT_STATUS_IS_OK(status)) {
5793                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5794                 goto fail;
5795         }
5796
5797         status = cli_close(cli1, fnum1);
5798         if (!NT_STATUS_IS_OK(status)) {
5799                 printf("[11] close failed (%s)\n", nt_errstr(status));
5800                 goto fail;
5801         }
5802
5803         /* Now try open for delete access. */
5804         status = cli_ntcreate(cli1, fname, 0,
5805                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5806                              0,
5807                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5808                              FILE_OPEN, 0, 0, &fnum1, NULL);
5809         if (!NT_STATUS_IS_OK(status)) {
5810                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5811                 goto fail;
5812         }
5813
5814         cli_close(cli1, fnum1);
5815
5816         printf("eleventh delete on close test succeeded.\n");
5817
5818         /*
5819          * Test 12
5820          * like test 4 but with initial delete on close
5821          */
5822
5823         cli_setatr(cli1, fname, 0, 0);
5824         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5825
5826         status = cli_ntcreate(cli1, fname, 0,
5827                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5828                               FILE_ATTRIBUTE_NORMAL,
5829                               FILE_SHARE_READ|FILE_SHARE_WRITE,
5830                               FILE_OVERWRITE_IF,
5831                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5832         if (!NT_STATUS_IS_OK(status)) {
5833                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5834                 goto fail;
5835         }
5836
5837         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5838                               FILE_ATTRIBUTE_NORMAL,
5839                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5840                               FILE_OPEN, 0, 0, &fnum2, NULL);
5841         if (!NT_STATUS_IS_OK(status)) {
5842                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5843                 goto fail;
5844         }
5845
5846         status = cli_close(cli1, fnum2);
5847         if (!NT_STATUS_IS_OK(status)) {
5848                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5849                 goto fail;
5850         }
5851
5852         status = cli_nt_delete_on_close(cli1, fnum1, true);
5853         if (!NT_STATUS_IS_OK(status)) {
5854                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5855                 goto fail;
5856         }
5857
5858         /* This should fail - no more opens once delete on close set. */
5859         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5860                               FILE_ATTRIBUTE_NORMAL,
5861                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5862                               FILE_OPEN, 0, 0, &fnum2, NULL);
5863         if (NT_STATUS_IS_OK(status)) {
5864                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5865                 goto fail;
5866         }
5867
5868         status = cli_nt_delete_on_close(cli1, fnum1, false);
5869         if (!NT_STATUS_IS_OK(status)) {
5870                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5871                 goto fail;
5872         }
5873
5874         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5875                               FILE_ATTRIBUTE_NORMAL,
5876                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5877                               FILE_OPEN, 0, 0, &fnum2, NULL);
5878         if (!NT_STATUS_IS_OK(status)) {
5879                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5880                 goto fail;
5881         }
5882
5883         status = cli_close(cli1, fnum2);
5884         if (!NT_STATUS_IS_OK(status)) {
5885                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5886                 goto fail;
5887         }
5888
5889         status = cli_close(cli1, fnum1);
5890         if (!NT_STATUS_IS_OK(status)) {
5891                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5892                 goto fail;
5893         }
5894
5895         /*
5896          * setting delete on close on the handle does
5897          * not unset the initial delete on close...
5898          */
5899         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5900                               FILE_ATTRIBUTE_NORMAL,
5901                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5902                               FILE_OPEN, 0, 0, &fnum2, NULL);
5903         if (NT_STATUS_IS_OK(status)) {
5904                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5905                 goto fail;
5906         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5907                 printf("ntcreate returned %s, expected "
5908                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5909                        nt_errstr(status));
5910                 goto fail;
5911         }
5912
5913         printf("twelfth delete on close test succeeded.\n");
5914
5915
5916         printf("finished delete test\n");
5917
5918         correct = true;
5919
5920   fail:
5921         /* FIXME: This will crash if we aborted before cli2 got
5922          * initialized, because these functions don't handle
5923          * uninitialized connections. */
5924
5925         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5926         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5927         cli_setatr(cli1, fname, 0, 0);
5928         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5929
5930         if (cli1 && !torture_close_connection(cli1)) {
5931                 correct = False;
5932         }
5933         if (cli2 && !torture_close_connection(cli2)) {
5934                 correct = False;
5935         }
5936         return correct;
5937 }
5938
5939 struct delete_stream_state {
5940         bool closed;
5941 };
5942
5943 static void delete_stream_unlinked(struct tevent_req *subreq);
5944 static void delete_stream_closed(struct tevent_req *subreq);
5945
5946 static struct tevent_req *delete_stream_send(
5947         TALLOC_CTX *mem_ctx,
5948         struct tevent_context *ev,
5949         struct cli_state *cli,
5950         const char *base_fname,
5951         uint16_t stream_fnum)
5952 {
5953         struct tevent_req *req = NULL, *subreq = NULL;
5954         struct delete_stream_state *state = NULL;
5955
5956         req = tevent_req_create(
5957                 mem_ctx, &state, struct delete_stream_state);
5958         if (req == NULL) {
5959                 return NULL;
5960         }
5961
5962         subreq = cli_unlink_send(
5963                 state,
5964                 ev,
5965                 cli,
5966                 base_fname,
5967                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5968         if (tevent_req_nomem(subreq, req)) {
5969                 return tevent_req_post(req, ev);
5970         }
5971         tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5972
5973         subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5974         if (tevent_req_nomem(subreq, req)) {
5975                 return tevent_req_post(req, ev);
5976         }
5977         tevent_req_set_callback(subreq, delete_stream_closed, req);
5978
5979         return req;
5980 }
5981
5982 static void delete_stream_unlinked(struct tevent_req *subreq)
5983 {
5984         struct tevent_req *req = tevent_req_callback_data(
5985                 subreq, struct tevent_req);
5986         struct delete_stream_state *state = tevent_req_data(
5987                 req, struct delete_stream_state);
5988         NTSTATUS status;
5989
5990         status = cli_unlink_recv(subreq);
5991         TALLOC_FREE(subreq);
5992         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5993                 printf("cli_unlink returned %s\n",
5994                        nt_errstr(status));
5995                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5996                 return;
5997         }
5998         if (!state->closed) {
5999                 /* close reply should have come in first */
6000                 printf("Not closed\n");
6001                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6002                 return;
6003         }
6004         tevent_req_done(req);
6005 }
6006
6007 static void delete_stream_closed(struct tevent_req *subreq)
6008 {
6009         struct tevent_req *req = tevent_req_callback_data(
6010                 subreq, struct tevent_req);
6011         struct delete_stream_state *state = tevent_req_data(
6012                 req, struct delete_stream_state);
6013         NTSTATUS status;
6014
6015         status = cli_close_recv(subreq);
6016         TALLOC_FREE(subreq);
6017         if (tevent_req_nterror(req, status)) {
6018                 return;
6019         }
6020         /* also waiting for the unlink to come back */
6021         state->closed = true;
6022 }
6023
6024 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6025 {
6026         return tevent_req_simple_recv_ntstatus(req);
6027 }
6028
6029 static bool run_delete_stream(int dummy)
6030 {
6031         struct tevent_context *ev = NULL;
6032         struct tevent_req *req = NULL;
6033         struct cli_state *cli = NULL;
6034         const char fname[] = "delete_stream";
6035         const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6036         uint16_t fnum1, fnum2;
6037         NTSTATUS status;
6038         bool ok;
6039
6040         printf("Starting stream delete test\n");
6041
6042         ok = torture_open_connection(&cli, 0);
6043         if (!ok) {
6044                 return false;
6045         }
6046
6047         cli_setatr(cli, fname, 0, 0);
6048         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6049
6050         /* Create the file. */
6051         status = cli_ntcreate(
6052                 cli,
6053                 fname,
6054                 0,
6055                 READ_CONTROL_ACCESS,
6056                 0,
6057                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6058                 FILE_CREATE,
6059                 0x0,
6060                 0x0,
6061                 &fnum1,
6062                 NULL);
6063         if (!NT_STATUS_IS_OK(status)) {
6064                 d_fprintf(stderr,
6065                           "cli_ntcreate of %s failed (%s)\n",
6066                           fname,
6067                           nt_errstr(status));
6068                 return false;
6069         }
6070         status = cli_close(cli, fnum1);
6071         if (!NT_STATUS_IS_OK(status)) {
6072                 d_fprintf(stderr,
6073                           "cli_close of %s failed (%s)\n",
6074                           fname,
6075                           nt_errstr(status));
6076                 return false;
6077         }
6078
6079         /* Now create the stream. */
6080         status = cli_ntcreate(
6081                 cli,
6082                 fname_stream,
6083                 0,
6084                 FILE_WRITE_DATA,
6085                 0,
6086                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6087                 FILE_CREATE,
6088                 0x0,
6089                 0x0,
6090                 &fnum1,
6091                 NULL);
6092
6093         if (!NT_STATUS_IS_OK(status)) {
6094                 d_fprintf(stderr,
6095                           "cli_ntcreate of %s failed (%s)\n",
6096                           fname_stream,
6097                           nt_errstr(status));
6098                 return false;
6099         }
6100
6101         /* open it a second time */
6102
6103         status = cli_ntcreate(
6104                 cli,
6105                 fname_stream,
6106                 0,
6107                 FILE_WRITE_DATA,
6108                 0,
6109                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6110                 FILE_OPEN,
6111                 0x0,
6112                 0x0,
6113                 &fnum2,
6114                 NULL);
6115
6116         if (!NT_STATUS_IS_OK(status)) {
6117                 d_fprintf(stderr,
6118                           "2nd cli_ntcreate of %s failed (%s)\n",
6119                           fname_stream,
6120                           nt_errstr(status));
6121                 return false;
6122         }
6123
6124         ev = samba_tevent_context_init(talloc_tos());
6125         if (ev == NULL) {
6126                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6127                 return false;
6128         }
6129
6130         req = delete_stream_send(ev, ev, cli, fname, fnum1);
6131         if (req == NULL) {
6132                 d_fprintf(stderr, "delete_stream_send failed\n");
6133                 return false;
6134         }
6135
6136         ok = tevent_req_poll_ntstatus(req, ev, &status);
6137         if (!ok) {
6138                 d_fprintf(stderr,
6139                           "tevent_req_poll_ntstatus failed: %s\n",
6140                           nt_errstr(status));
6141                 return false;
6142         }
6143
6144         status = delete_stream_recv(req);
6145         TALLOC_FREE(req);
6146         if (!NT_STATUS_IS_OK(status)) {
6147                 d_fprintf(stderr,
6148                           "delete_stream failed: %s\n",
6149                           nt_errstr(status));
6150                 return false;
6151         }
6152
6153         status = cli_close(cli, fnum2);
6154         if (!NT_STATUS_IS_OK(status)) {
6155                 d_fprintf(stderr,
6156                           "close failed: %s\n",
6157                           nt_errstr(status));
6158                 return false;
6159         }
6160
6161         status = cli_unlink(
6162                 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6163         if (!NT_STATUS_IS_OK(status)) {
6164                 d_fprintf(stderr,
6165                           "unlink failed: %s\n",
6166                           nt_errstr(status));
6167                 return false;
6168         }
6169
6170         return true;
6171 }
6172
6173 /*
6174   Exercise delete on close semantics - use on the PRINT1 share in torture
6175   testing.
6176  */
6177 static bool run_delete_print_test(int dummy)
6178 {
6179         struct cli_state *cli1 = NULL;
6180         const char *fname = "print_delete.file";
6181         uint16_t fnum1 = (uint16_t)-1;
6182         bool correct = false;
6183         const char *buf = "print file data\n";
6184         NTSTATUS status;
6185
6186         printf("starting print delete test\n");
6187
6188         if (!torture_open_connection(&cli1, 0)) {
6189                 return false;
6190         }
6191
6192         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6193
6194         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6195                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6196                               0, 0, &fnum1, NULL);
6197         if (!NT_STATUS_IS_OK(status)) {
6198                 printf("open of %s failed (%s)\n",
6199                         fname,
6200                         nt_errstr(status));
6201                 goto fail;
6202         }
6203
6204         status = cli_writeall(cli1,
6205                         fnum1,
6206                         0,
6207                         (const uint8_t *)buf,
6208                         0, /* offset */
6209                         strlen(buf), /* size */
6210                         NULL);
6211         if (!NT_STATUS_IS_OK(status)) {
6212                 printf("writing print file data failed (%s)\n",
6213                         nt_errstr(status));
6214                 goto fail;
6215         }
6216
6217         status = cli_nt_delete_on_close(cli1, fnum1, true);
6218         if (!NT_STATUS_IS_OK(status)) {
6219                 printf("setting delete_on_close failed (%s)\n",
6220                         nt_errstr(status));
6221                 goto fail;
6222         }
6223
6224         status = cli_close(cli1, fnum1);
6225         if (!NT_STATUS_IS_OK(status)) {
6226                 printf("close failed (%s)\n", nt_errstr(status));
6227                 goto fail;
6228         }
6229
6230         printf("finished print delete test\n");
6231
6232         correct = true;
6233
6234   fail:
6235
6236         if (fnum1 != (uint16_t)-1) {
6237                 cli_close(cli1, fnum1);
6238         }
6239
6240         if (cli1 && !torture_close_connection(cli1)) {
6241                 correct = false;
6242         }
6243         return correct;
6244 }
6245
6246 static bool run_deletetest_ln(int dummy)
6247 {
6248         struct cli_state *cli;
6249         const char *fname = "\\delete1";
6250         const char *fname_ln = "\\delete1_ln";
6251         uint16_t fnum;
6252         uint16_t fnum1;
6253         NTSTATUS status;
6254         bool correct = true;
6255         time_t t;
6256
6257         printf("starting deletetest-ln\n");
6258
6259         if (!torture_open_connection(&cli, 0)) {
6260                 return false;
6261         }
6262
6263         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6264         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6265
6266         smbXcli_conn_set_sockopt(cli->conn, sockops);
6267
6268         /* Create the file. */
6269         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6270         if (!NT_STATUS_IS_OK(status)) {
6271                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6272                 return false;
6273         }
6274
6275         status = cli_close(cli, fnum);
6276         if (!NT_STATUS_IS_OK(status)) {
6277                 printf("close1 failed (%s)\n", nt_errstr(status));
6278                 return false;
6279         }
6280
6281         /* Now create a hardlink. */
6282         status = cli_hardlink(cli, fname, fname_ln);
6283         if (!NT_STATUS_IS_OK(status)) {
6284                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6285                 return false;
6286         }
6287
6288         /* Open the original file. */
6289         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6290                         FILE_ATTRIBUTE_NORMAL,
6291                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6292                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
6293         if (!NT_STATUS_IS_OK(status)) {
6294                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6295                 return false;
6296         }
6297
6298         /* Unlink the hard link path. */
6299         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6300                         FILE_ATTRIBUTE_NORMAL,
6301                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6302                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6303         if (!NT_STATUS_IS_OK(status)) {
6304                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6305                 return false;
6306         }
6307         status = cli_nt_delete_on_close(cli, fnum1, true);
6308         if (!NT_STATUS_IS_OK(status)) {
6309                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6310                         __location__, fname_ln, nt_errstr(status));
6311                 return false;
6312         }
6313
6314         status = cli_close(cli, fnum1);
6315         if (!NT_STATUS_IS_OK(status)) {
6316                 printf("close %s failed (%s)\n",
6317                         fname_ln, nt_errstr(status));
6318                 return false;
6319         }
6320
6321         status = cli_close(cli, fnum);
6322         if (!NT_STATUS_IS_OK(status)) {
6323                 printf("close %s failed (%s)\n",
6324                         fname, nt_errstr(status));
6325                 return false;
6326         }
6327
6328         /* Ensure the original file is still there. */
6329         status = cli_getatr(cli, fname, NULL, NULL, &t);
6330         if (!NT_STATUS_IS_OK(status)) {
6331                 printf("%s getatr on file %s failed (%s)\n",
6332                         __location__,
6333                         fname,
6334                         nt_errstr(status));
6335                 correct = False;
6336         }
6337
6338         /* Ensure the link path is gone. */
6339         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6340         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6341                 printf("%s, getatr for file %s returned wrong error code %s "
6342                         "- should have been deleted\n",
6343                         __location__,
6344                         fname_ln, nt_errstr(status));
6345                 correct = False;
6346         }
6347
6348         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6349         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6350
6351         if (!torture_close_connection(cli)) {
6352                 correct = false;
6353         }
6354
6355         printf("finished deletetest-ln\n");
6356
6357         return correct;
6358 }
6359
6360 /*
6361   print out server properties
6362  */
6363 static bool run_properties(int dummy)
6364 {
6365         struct cli_state *cli;
6366         bool correct = True;
6367
6368         printf("starting properties test\n");
6369
6370         ZERO_STRUCT(cli);
6371
6372         if (!torture_open_connection(&cli, 0)) {
6373                 return False;
6374         }
6375
6376         smbXcli_conn_set_sockopt(cli->conn, sockops);
6377
6378         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6379
6380         if (!torture_close_connection(cli)) {
6381                 correct = False;
6382         }
6383
6384         return correct;
6385 }
6386
6387
6388
6389 /* FIRST_DESIRED_ACCESS   0xf019f */
6390 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6391                                FILE_READ_EA|                           /* 0xf */ \
6392                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
6393                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
6394                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
6395                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
6396 /* SECOND_DESIRED_ACCESS  0xe0080 */
6397 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6398                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6399                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
6400
6401 #if 0
6402 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
6403                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6404                                FILE_READ_DATA|\
6405                                WRITE_OWNER_ACCESS                      /* */
6406 #endif
6407
6408 /*
6409   Test ntcreate calls made by xcopy
6410  */
6411 static bool run_xcopy(int dummy)
6412 {
6413         static struct cli_state *cli1;
6414         const char *fname = "\\test.txt";
6415         bool correct = True;
6416         uint16_t fnum1, fnum2;
6417         NTSTATUS status;
6418
6419         printf("starting xcopy test\n");
6420
6421         if (!torture_open_connection(&cli1, 0)) {
6422                 return False;
6423         }
6424
6425         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6426                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6427                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6428         if (!NT_STATUS_IS_OK(status)) {
6429                 printf("First open failed - %s\n", nt_errstr(status));
6430                 return False;
6431         }
6432
6433         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6434                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6435                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6436         if (!NT_STATUS_IS_OK(status)) {
6437                 printf("second open failed - %s\n", nt_errstr(status));
6438                 return False;
6439         }
6440
6441         if (!torture_close_connection(cli1)) {
6442                 correct = False;
6443         }
6444
6445         return correct;
6446 }
6447
6448 /*
6449   Test rename on files open with share delete and no share delete.
6450  */
6451 static bool run_rename(int dummy)
6452 {
6453         static struct cli_state *cli1;
6454         const char *fname = "\\test.txt";
6455         const char *fname1 = "\\test1.txt";
6456         bool correct = True;
6457         uint16_t fnum1;
6458         uint32_t attr;
6459         NTSTATUS status;
6460
6461         printf("starting rename test\n");
6462
6463         if (!torture_open_connection(&cli1, 0)) {
6464                 return False;
6465         }
6466
6467         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6469
6470         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6471                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6472                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6473         if (!NT_STATUS_IS_OK(status)) {
6474                 printf("First open failed - %s\n", nt_errstr(status));
6475                 return False;
6476         }
6477
6478         status = cli_rename(cli1, fname, fname1, false);
6479         if (!NT_STATUS_IS_OK(status)) {
6480                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6481         } else {
6482                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6483                 correct = False;
6484         }
6485
6486         status = cli_close(cli1, fnum1);
6487         if (!NT_STATUS_IS_OK(status)) {
6488                 printf("close - 1 failed (%s)\n", nt_errstr(status));
6489                 return False;
6490         }
6491
6492         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6493         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6494         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6495 #if 0
6496                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
6497 #else
6498                               FILE_SHARE_DELETE|FILE_SHARE_READ,
6499 #endif
6500                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6501         if (!NT_STATUS_IS_OK(status)) {
6502                 printf("Second open failed - %s\n", nt_errstr(status));
6503                 return False;
6504         }
6505
6506         status = cli_rename(cli1, fname, fname1, false);
6507         if (!NT_STATUS_IS_OK(status)) {
6508                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6509                 correct = False;
6510         } else {
6511                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6512         }
6513
6514         status = cli_close(cli1, fnum1);
6515         if (!NT_STATUS_IS_OK(status)) {
6516                 printf("close - 2 failed (%s)\n", nt_errstr(status));
6517                 return False;
6518         }
6519
6520         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6521         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6522
6523         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6524                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6525                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6526         if (!NT_STATUS_IS_OK(status)) {
6527                 printf("Third open failed - %s\n", nt_errstr(status));
6528                 return False;
6529         }
6530
6531
6532         status = cli_rename(cli1, fname, fname1, false);
6533         if (!NT_STATUS_IS_OK(status)) {
6534                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6535                 correct = False;
6536         } else {
6537                 printf("Third rename succeeded (SHARE_NONE)\n");
6538         }
6539
6540         status = cli_close(cli1, fnum1);
6541         if (!NT_STATUS_IS_OK(status)) {
6542                 printf("close - 3 failed (%s)\n", nt_errstr(status));
6543                 return False;
6544         }
6545
6546         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6547         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6548
6549         /*----*/
6550
6551         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6552                               FILE_ATTRIBUTE_NORMAL,
6553                               FILE_SHARE_READ | FILE_SHARE_WRITE,
6554                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6555         if (!NT_STATUS_IS_OK(status)) {
6556                 printf("Fourth open failed - %s\n", nt_errstr(status));
6557                 return False;
6558         }
6559
6560         status = cli_rename(cli1, fname, fname1, false);
6561         if (!NT_STATUS_IS_OK(status)) {
6562                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6563         } else {
6564                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6565                 correct = False;
6566         }
6567
6568         status = cli_close(cli1, fnum1);
6569         if (!NT_STATUS_IS_OK(status)) {
6570                 printf("close - 4 failed (%s)\n", nt_errstr(status));
6571                 return False;
6572         }
6573
6574         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6575         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6576
6577         /*--*/
6578
6579         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6580                          FILE_ATTRIBUTE_NORMAL,
6581                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6582                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6583         if (!NT_STATUS_IS_OK(status)) {
6584                 printf("Fifth open failed - %s\n", nt_errstr(status));
6585                 return False;
6586         }
6587
6588         status = cli_rename(cli1, fname, fname1, false);
6589         if (!NT_STATUS_IS_OK(status)) {
6590                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6591                 correct = False;
6592         } else {
6593                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6594         }
6595
6596         /*--*/
6597         status = cli_close(cli1, fnum1);
6598         if (!NT_STATUS_IS_OK(status)) {
6599                 printf("close - 5 failed (%s)\n", nt_errstr(status));
6600                 return False;
6601         }
6602
6603         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6604         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6605         if (!NT_STATUS_IS_OK(status)) {
6606                 printf("getatr on file %s failed - %s ! \n",
6607                         fname1, nt_errstr(status));
6608                 correct = False;
6609         } else {
6610                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6611                         printf("Renamed file %s has wrong attr 0x%x "
6612                                 "(should be 0x%x)\n",
6613                                 fname1,
6614                                 attr,
6615                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6616                         correct = False;
6617                 } else {
6618                         printf("Renamed file %s has archive bit set\n", fname1);
6619                 }
6620         }
6621
6622         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6623         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6624
6625         if (!torture_close_connection(cli1)) {
6626                 correct = False;
6627         }
6628
6629         return correct;
6630 }
6631
6632 /*
6633   Test rename into a directory with an ACL denying it.
6634  */
6635 static bool run_rename_access(int dummy)
6636 {
6637         static struct cli_state *cli = NULL;
6638         static struct cli_state *posix_cli = NULL;
6639         const char *src = "test.txt";
6640         const char *dname = "dir";
6641         const char *dst = "dir\\test.txt";
6642         const char *dsrc = "test.dir";
6643         const char *ddst = "dir\\test.dir";
6644         uint16_t fnum = (uint16_t)-1;
6645         struct security_descriptor *sd = NULL;
6646         struct security_descriptor *newsd = NULL;
6647         NTSTATUS status;
6648         TALLOC_CTX *frame = NULL;
6649
6650         frame = talloc_stackframe();
6651         printf("starting rename access test\n");
6652
6653         /* Windows connection. */
6654         if (!torture_open_connection(&cli, 0)) {
6655                 goto fail;
6656         }
6657
6658         smbXcli_conn_set_sockopt(cli->conn, sockops);
6659
6660         /* Posix connection. */
6661         if (!torture_open_connection(&posix_cli, 0)) {
6662                 goto fail;
6663         }
6664
6665         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6666
6667         status = torture_setup_unix_extensions(posix_cli);
6668         if (!NT_STATUS_IS_OK(status)) {
6669                 goto fail;
6670         }
6671
6672         /* Start with a clean slate. */
6673         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6674         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6675         cli_rmdir(cli, dsrc);
6676         cli_rmdir(cli, ddst);
6677         cli_rmdir(cli, dname);
6678
6679         /*
6680          * Setup the destination directory with a DENY ACE to
6681          * prevent new files within it.
6682          */
6683         status = cli_ntcreate(cli,
6684                                 dname,
6685                                 0,
6686                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6687                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
6688                                         WRITE_OWNER_ACCESS,
6689                                 FILE_ATTRIBUTE_DIRECTORY,
6690                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
6691                                 FILE_CREATE,
6692                                 FILE_DIRECTORY_FILE,
6693                                 0,
6694                                 &fnum,
6695                                 NULL);
6696         if (!NT_STATUS_IS_OK(status)) {
6697                 printf("Create of %s - %s\n", dname, nt_errstr(status));
6698                 goto fail;
6699         }
6700
6701         status = cli_query_secdesc(cli,
6702                                 fnum,
6703                                 frame,
6704                                 &sd);
6705         if (!NT_STATUS_IS_OK(status)) {
6706                 printf("cli_query_secdesc failed for %s (%s)\n",
6707                         dname, nt_errstr(status));
6708                 goto fail;
6709         }
6710
6711         newsd = security_descriptor_dacl_create(frame,
6712                                         0,
6713                                         NULL,
6714                                         NULL,
6715                                         SID_WORLD,
6716                                         SEC_ACE_TYPE_ACCESS_DENIED,
6717                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6718                                         0,
6719                                         NULL);
6720         if (newsd == NULL) {
6721                 goto fail;
6722         }
6723         sd->dacl = security_acl_concatenate(frame,
6724                                         newsd->dacl,
6725                                         sd->dacl);
6726         if (sd->dacl == NULL) {
6727                 goto fail;
6728         }
6729         status = cli_set_secdesc(cli, fnum, sd);
6730         if (!NT_STATUS_IS_OK(status)) {
6731                 printf("cli_set_secdesc failed for %s (%s)\n",
6732                         dname, nt_errstr(status));
6733                 goto fail;
6734         }
6735         status = cli_close(cli, fnum);
6736         if (!NT_STATUS_IS_OK(status)) {
6737                 printf("close failed for %s (%s)\n",
6738                         dname, nt_errstr(status));
6739                 goto fail;
6740         }
6741         /* Now go around the back and chmod to 777 via POSIX. */
6742         status = cli_posix_chmod(posix_cli, dname, 0777);
6743         if (!NT_STATUS_IS_OK(status)) {
6744                 printf("cli_posix_chmod failed for %s (%s)\n",
6745                         dname, nt_errstr(status));
6746                 goto fail;
6747         }
6748
6749         /* Check we can't create a file within dname via Windows. */
6750         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6751         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6752                 cli_close(posix_cli, fnum);
6753                 printf("Create of %s should be ACCESS denied, was %s\n",
6754                         dst, nt_errstr(status));
6755                 goto fail;
6756         }
6757
6758         /* Make the sample file/directory. */
6759         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6760         if (!NT_STATUS_IS_OK(status)) {
6761                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6762                 goto fail;
6763         }
6764         status = cli_close(cli, fnum);
6765         if (!NT_STATUS_IS_OK(status)) {
6766                 printf("cli_close failed (%s)\n", nt_errstr(status));
6767                 goto fail;
6768         }
6769
6770         status = cli_mkdir(cli, dsrc);
6771         if (!NT_STATUS_IS_OK(status)) {
6772                 printf("cli_mkdir of %s failed (%s)\n",
6773                         dsrc, nt_errstr(status));
6774                 goto fail;
6775         }
6776
6777         /*
6778          * OK - renames of the new file and directory into the
6779          * dst directory should fail.
6780          */
6781
6782         status = cli_rename(cli, src, dst, false);
6783         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6784                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6785                         src, dst, nt_errstr(status));
6786                 goto fail;
6787         }
6788         status = cli_rename(cli, dsrc, ddst, false);
6789         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6790                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6791                         src, dst, nt_errstr(status));
6792                 goto fail;
6793         }
6794
6795         TALLOC_FREE(frame);
6796         return true;
6797
6798   fail:
6799
6800         if (posix_cli) {
6801                 torture_close_connection(posix_cli);
6802         }
6803
6804         if (cli) {
6805                 if (fnum != (uint16_t)-1) {
6806                         cli_close(cli, fnum);
6807                 }
6808                 cli_unlink(cli, src,
6809                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6810                 cli_unlink(cli, dst,
6811                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6812                 cli_rmdir(cli, dsrc);
6813                 cli_rmdir(cli, ddst);
6814                 cli_rmdir(cli, dname);
6815
6816                 torture_close_connection(cli);
6817         }
6818
6819         TALLOC_FREE(frame);
6820         return false;
6821 }
6822
6823 /*
6824   Test owner rights ACE.
6825  */
6826 static bool run_owner_rights(int dummy)
6827 {
6828         static struct cli_state *cli = NULL;
6829         const char *fname = "owner_rights.txt";
6830         uint16_t fnum = (uint16_t)-1;
6831         struct security_descriptor *sd = NULL;
6832         struct security_descriptor *newsd = NULL;
6833         NTSTATUS status;
6834         TALLOC_CTX *frame = NULL;
6835
6836         frame = talloc_stackframe();
6837         printf("starting owner rights test\n");
6838
6839         /* Windows connection. */
6840         if (!torture_open_connection(&cli, 0)) {
6841                 goto fail;
6842         }
6843
6844         smbXcli_conn_set_sockopt(cli->conn, sockops);
6845
6846         /* Start with a clean slate. */
6847         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6848
6849         /* Create the test file. */
6850         /* Now try and open for read and write-dac. */
6851         status = cli_ntcreate(cli,
6852                                 fname,
6853                                 0,
6854                                 GENERIC_ALL_ACCESS,
6855                                 FILE_ATTRIBUTE_NORMAL,
6856                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6857                                         FILE_SHARE_DELETE,
6858                                 FILE_CREATE,
6859                                 0,
6860                                 0,
6861                                 &fnum,
6862                                 NULL);
6863         if (!NT_STATUS_IS_OK(status)) {
6864                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6865                 goto fail;
6866         }
6867
6868         /* Get the original SD. */
6869         status = cli_query_secdesc(cli,
6870                                 fnum,
6871                                 frame,
6872                                 &sd);
6873         if (!NT_STATUS_IS_OK(status)) {
6874                 printf("cli_query_secdesc failed for %s (%s)\n",
6875                         fname, nt_errstr(status));
6876                 goto fail;
6877         }
6878
6879         /*
6880          * Add an "owner-rights" ACE denying WRITE_DATA,
6881          * and an "owner-rights" ACE allowing READ_DATA.
6882          */
6883
6884         newsd = security_descriptor_dacl_create(frame,
6885                                         0,
6886                                         NULL,
6887                                         NULL,
6888                                         SID_OWNER_RIGHTS,
6889                                         SEC_ACE_TYPE_ACCESS_DENIED,
6890                                         FILE_WRITE_DATA,
6891                                         0,
6892                                         SID_OWNER_RIGHTS,
6893                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
6894                                         FILE_READ_DATA,
6895                                         0,
6896                                         NULL);
6897         if (newsd == NULL) {
6898                 goto fail;
6899         }
6900         sd->dacl = security_acl_concatenate(frame,
6901                                         newsd->dacl,
6902                                         sd->dacl);
6903         if (sd->dacl == NULL) {
6904                 goto fail;
6905         }
6906         status = cli_set_secdesc(cli, fnum, sd);
6907         if (!NT_STATUS_IS_OK(status)) {
6908                 printf("cli_set_secdesc failed for %s (%s)\n",
6909                         fname, nt_errstr(status));
6910                 goto fail;
6911         }
6912         status = cli_close(cli, fnum);
6913         if (!NT_STATUS_IS_OK(status)) {
6914                 printf("close failed for %s (%s)\n",
6915                         fname, nt_errstr(status));
6916                 goto fail;
6917         }
6918         fnum = (uint16_t)-1;
6919
6920         /* Try and open for FILE_WRITE_DATA */
6921         status = cli_ntcreate(cli,
6922                                 fname,
6923                                 0,
6924                                 FILE_WRITE_DATA,
6925                                 FILE_ATTRIBUTE_NORMAL,
6926                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6927                                         FILE_SHARE_DELETE,
6928                                 FILE_OPEN,
6929                                 0,
6930                                 0,
6931                                 &fnum,
6932                                 NULL);
6933         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6934                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6935                 goto fail;
6936         }
6937
6938         /* Now try and open for FILE_READ_DATA */
6939         status = cli_ntcreate(cli,
6940                                 fname,
6941                                 0,
6942                                 FILE_READ_DATA,
6943                                 FILE_ATTRIBUTE_NORMAL,
6944                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6945                                         FILE_SHARE_DELETE,
6946                                 FILE_OPEN,
6947                                 0,
6948                                 0,
6949                                 &fnum,
6950                                 NULL);
6951         if (!NT_STATUS_IS_OK(status)) {
6952                 printf("Open of %s - %s\n", fname, nt_errstr(status));
6953                 goto fail;
6954         }
6955
6956         status = cli_close(cli, fnum);
6957         if (!NT_STATUS_IS_OK(status)) {
6958                 printf("close failed for %s (%s)\n",
6959                         fname, nt_errstr(status));
6960                 goto fail;
6961         }
6962
6963         /* Restore clean slate. */
6964         TALLOC_FREE(sd);
6965         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6966
6967         /* Create the test file. */
6968         status = cli_ntcreate(cli,
6969                                 fname,
6970                                 0,
6971                                 GENERIC_ALL_ACCESS,
6972                                 FILE_ATTRIBUTE_NORMAL,
6973                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
6974                                         FILE_SHARE_DELETE,
6975                                 FILE_CREATE,
6976                                 0,
6977                                 0,
6978                                 &fnum,
6979                                 NULL);
6980         if (!NT_STATUS_IS_OK(status)) {
6981                 printf("Create of %s - %s\n", fname, nt_errstr(status));
6982                 goto fail;
6983         }
6984
6985         /* Get the original SD. */
6986         status = cli_query_secdesc(cli,
6987                                 fnum,
6988                                 frame,
6989                                 &sd);
6990         if (!NT_STATUS_IS_OK(status)) {
6991                 printf("cli_query_secdesc failed for %s (%s)\n",
6992                         fname, nt_errstr(status));
6993                 goto fail;
6994         }
6995
6996         /*
6997          * Add an "owner-rights ACE denying WRITE_DATA,
6998          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6999          */
7000
7001         newsd = security_descriptor_dacl_create(frame,
7002                                         0,
7003                                         NULL,
7004                                         NULL,
7005                                         SID_OWNER_RIGHTS,
7006                                         SEC_ACE_TYPE_ACCESS_DENIED,
7007                                         FILE_WRITE_DATA,
7008                                         0,
7009                                         SID_OWNER_RIGHTS,
7010                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7011                                         FILE_READ_DATA|FILE_WRITE_DATA,
7012                                         0,
7013                                         NULL);
7014         if (newsd == NULL) {
7015                 goto fail;
7016         }
7017         sd->dacl = security_acl_concatenate(frame,
7018                                         newsd->dacl,
7019                                         sd->dacl);
7020         if (sd->dacl == NULL) {
7021                 goto fail;
7022         }
7023         status = cli_set_secdesc(cli, fnum, sd);
7024         if (!NT_STATUS_IS_OK(status)) {
7025                 printf("cli_set_secdesc failed for %s (%s)\n",
7026                         fname, nt_errstr(status));
7027                 goto fail;
7028         }
7029         status = cli_close(cli, fnum);
7030         if (!NT_STATUS_IS_OK(status)) {
7031                 printf("close failed for %s (%s)\n",
7032                         fname, nt_errstr(status));
7033                 goto fail;
7034         }
7035         fnum = (uint16_t)-1;
7036
7037         /* Try and open for FILE_WRITE_DATA */
7038         status = cli_ntcreate(cli,
7039                                 fname,
7040                                 0,
7041                                 FILE_WRITE_DATA,
7042                                 FILE_ATTRIBUTE_NORMAL,
7043                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7044                                         FILE_SHARE_DELETE,
7045                                 FILE_OPEN,
7046                                 0,
7047                                 0,
7048                                 &fnum,
7049                                 NULL);
7050         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7051                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7052                 goto fail;
7053         }
7054
7055         /* Now try and open for FILE_READ_DATA */
7056         status = cli_ntcreate(cli,
7057                                 fname,
7058                                 0,
7059                                 FILE_READ_DATA,
7060                                 FILE_ATTRIBUTE_NORMAL,
7061                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7062                                         FILE_SHARE_DELETE,
7063                                 FILE_OPEN,
7064                                 0,
7065                                 0,
7066                                 &fnum,
7067                                 NULL);
7068         if (!NT_STATUS_IS_OK(status)) {
7069                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7070                 goto fail;
7071         }
7072
7073         status = cli_close(cli, fnum);
7074         if (!NT_STATUS_IS_OK(status)) {
7075                 printf("close failed for %s (%s)\n",
7076                         fname, nt_errstr(status));
7077                 goto fail;
7078         }
7079
7080         /* Restore clean slate. */
7081         TALLOC_FREE(sd);
7082         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7083
7084
7085         /* Create the test file. */
7086         status = cli_ntcreate(cli,
7087                                 fname,
7088                                 0,
7089                                 GENERIC_ALL_ACCESS,
7090                                 FILE_ATTRIBUTE_NORMAL,
7091                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7092                                         FILE_SHARE_DELETE,
7093                                 FILE_CREATE,
7094                                 0,
7095                                 0,
7096                                 &fnum,
7097                                 NULL);
7098         if (!NT_STATUS_IS_OK(status)) {
7099                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7100                 goto fail;
7101         }
7102
7103         /* Get the original SD. */
7104         status = cli_query_secdesc(cli,
7105                                 fnum,
7106                                 frame,
7107                                 &sd);
7108         if (!NT_STATUS_IS_OK(status)) {
7109                 printf("cli_query_secdesc failed for %s (%s)\n",
7110                         fname, nt_errstr(status));
7111                 goto fail;
7112         }
7113
7114         /*
7115          * Add an "authenticated users" ACE allowing READ_DATA,
7116          * add an "owner-rights" denying READ_DATA,
7117          * and an "authenticated users" ACE allowing WRITE_DATA.
7118          */
7119
7120         newsd = security_descriptor_dacl_create(frame,
7121                                         0,
7122                                         NULL,
7123                                         NULL,
7124                                         SID_NT_AUTHENTICATED_USERS,
7125                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7126                                         FILE_READ_DATA,
7127                                         0,
7128                                         SID_OWNER_RIGHTS,
7129                                         SEC_ACE_TYPE_ACCESS_DENIED,
7130                                         FILE_READ_DATA,
7131                                         0,
7132                                         SID_NT_AUTHENTICATED_USERS,
7133                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
7134                                         FILE_WRITE_DATA,
7135                                         0,
7136                                         NULL);
7137         if (newsd == NULL) {
7138                 printf("newsd == NULL\n");
7139                 goto fail;
7140         }
7141         sd->dacl = security_acl_concatenate(frame,
7142                                         newsd->dacl,
7143                                         sd->dacl);
7144         if (sd->dacl == NULL) {
7145                 printf("sd->dacl == NULL\n");
7146                 goto fail;
7147         }
7148         status = cli_set_secdesc(cli, fnum, sd);
7149         if (!NT_STATUS_IS_OK(status)) {
7150                 printf("cli_set_secdesc failed for %s (%s)\n",
7151                         fname, nt_errstr(status));
7152                 goto fail;
7153         }
7154         status = cli_close(cli, fnum);
7155         if (!NT_STATUS_IS_OK(status)) {
7156                 printf("close failed for %s (%s)\n",
7157                         fname, nt_errstr(status));
7158                 goto fail;
7159         }
7160         fnum = (uint16_t)-1;
7161
7162         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7163         status = cli_ntcreate(cli,
7164                                 fname,
7165                                 0,
7166                                 FILE_READ_DATA|FILE_WRITE_DATA,
7167                                 FILE_ATTRIBUTE_NORMAL,
7168                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7169                                         FILE_SHARE_DELETE,
7170                                 FILE_OPEN,
7171                                 0,
7172                                 0,
7173                                 &fnum,
7174                                 NULL);
7175         if (!NT_STATUS_IS_OK(status)) {
7176                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7177                 goto fail;
7178         }
7179
7180         status = cli_close(cli, fnum);
7181         if (!NT_STATUS_IS_OK(status)) {
7182                 printf("close failed for %s (%s)\n",
7183                         fname, nt_errstr(status));
7184                 goto fail;
7185         }
7186
7187         cli_unlink(cli, fname,
7188                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7189
7190         TALLOC_FREE(frame);
7191         return true;
7192
7193   fail:
7194
7195         if (cli) {
7196                 if (fnum != (uint16_t)-1) {
7197                         cli_close(cli, fnum);
7198                 }
7199                 cli_unlink(cli, fname,
7200                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7201                 torture_close_connection(cli);
7202         }
7203
7204         TALLOC_FREE(frame);
7205         return false;
7206 }
7207
7208 /*
7209  * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7210  * Note this test only works with a user with SeSecurityPrivilege set.
7211  *
7212  * NB. This is also tested in samba3.base.createx_access
7213  * but this makes it very explicit what we're looking for.
7214  */
7215 static bool run_smb1_system_security(int dummy)
7216 {
7217         static struct cli_state *cli = NULL;
7218         const char *fname = "system_security.txt";
7219         uint16_t fnum = (uint16_t)-1;
7220         NTSTATUS status;
7221         TALLOC_CTX *frame = NULL;
7222
7223         frame = talloc_stackframe();
7224         printf("starting smb1 system security test\n");
7225
7226         /* SMB1 connection - torture_open_connection() forces this. */
7227         if (!torture_open_connection(&cli, 0)) {
7228                 goto fail;
7229         }
7230
7231         smbXcli_conn_set_sockopt(cli->conn, sockops);
7232
7233         /* Start with a clean slate. */
7234         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7235
7236         /* Create the test file. */
7237         status = cli_ntcreate(cli,
7238                                 fname,
7239                                 0,
7240                                 GENERIC_ALL_ACCESS,
7241                                 FILE_ATTRIBUTE_NORMAL,
7242                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7243                                         FILE_SHARE_DELETE,
7244                                 FILE_CREATE,
7245                                 0,
7246                                 0,
7247                                 &fnum,
7248                                 NULL);
7249         if (!NT_STATUS_IS_OK(status)) {
7250                 printf("Create of %s - %s\n", fname, nt_errstr(status));
7251                 goto fail;
7252         }
7253
7254         status = cli_close(cli, fnum);
7255
7256         /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7257         /*
7258          * On SMB1 this succeeds - SMB2 it fails,
7259          * see the SMB2-SACL test.
7260          */
7261         status = cli_ntcreate(cli,
7262                                 fname,
7263                                 0,
7264                                 SEC_FLAG_SYSTEM_SECURITY,
7265                                 FILE_ATTRIBUTE_NORMAL,
7266                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
7267                                         FILE_SHARE_DELETE,
7268                                 FILE_OPEN,
7269                                 0,
7270                                 0,
7271                                 &fnum,
7272                                 NULL);
7273         if (!NT_STATUS_IS_OK(status)) {
7274                 printf("Open of %s - %s\n", fname, nt_errstr(status));
7275                 goto fail;
7276         }
7277
7278         status = cli_close(cli, fnum);
7279
7280         cli_unlink(cli, fname,
7281                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7282
7283         torture_close_connection(cli);
7284         TALLOC_FREE(frame);
7285         return true;
7286
7287   fail:
7288
7289         if (cli) {
7290                 if (fnum != (uint16_t)-1) {
7291                         cli_close(cli, fnum);
7292                 }
7293                 cli_unlink(cli, fname,
7294                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7295                 torture_close_connection(cli);
7296         }
7297
7298         TALLOC_FREE(frame);
7299         return false;
7300 }
7301
7302 static bool run_pipe_number(int dummy)
7303 {
7304         struct cli_state *cli1;
7305         const char *pipe_name = "\\SPOOLSS";
7306         uint16_t fnum;
7307         int num_pipes = 0;
7308         NTSTATUS status;
7309
7310         printf("starting pipenumber test\n");
7311         if (!torture_open_connection(&cli1, 0)) {
7312                 return False;
7313         }
7314
7315         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7316         while(1) {
7317                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7318                                       FILE_ATTRIBUTE_NORMAL,
7319                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
7320                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
7321                 if (!NT_STATUS_IS_OK(status)) {
7322                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7323                         break;
7324                 }
7325                 num_pipes++;
7326                 printf("\r%6d", num_pipes);
7327         }
7328
7329         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7330         torture_close_connection(cli1);
7331         return True;
7332 }
7333
7334 /*
7335   Test open mode returns on read-only files.
7336  */
7337 static bool run_opentest(int dummy)
7338 {
7339         static struct cli_state *cli1;
7340         static struct cli_state *cli2;
7341         const char *fname = "\\readonly.file";
7342         uint16_t fnum1, fnum2;
7343         char buf[20];
7344         off_t fsize;
7345         bool correct = True;
7346         char *tmp_path;
7347         NTSTATUS status;
7348
7349         printf("starting open test\n");
7350
7351         if (!torture_open_connection(&cli1, 0)) {
7352                 return False;
7353         }
7354
7355         cli_setatr(cli1, fname, 0, 0);
7356         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7357
7358         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7359
7360         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7361         if (!NT_STATUS_IS_OK(status)) {
7362                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7363                 return False;
7364         }
7365
7366         status = cli_close(cli1, fnum1);
7367         if (!NT_STATUS_IS_OK(status)) {
7368                 printf("close2 failed (%s)\n", nt_errstr(status));
7369                 return False;
7370         }
7371
7372         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7373         if (!NT_STATUS_IS_OK(status)) {
7374                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7375                 return False;
7376         }
7377
7378         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7379         if (!NT_STATUS_IS_OK(status)) {
7380                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7381                 return False;
7382         }
7383
7384         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7385         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7386
7387         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7388                         NT_STATUS_ACCESS_DENIED)) {
7389                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7390         }
7391
7392         printf("finished open test 1\n");
7393
7394         cli_close(cli1, fnum1);
7395
7396         /* Now try not readonly and ensure ERRbadshare is returned. */
7397
7398         cli_setatr(cli1, fname, 0, 0);
7399
7400         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7401         if (!NT_STATUS_IS_OK(status)) {
7402                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7403                 return False;
7404         }
7405
7406         /* This will fail - but the error should be ERRshare. */
7407         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7408
7409         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7410                         NT_STATUS_SHARING_VIOLATION)) {
7411                 printf("correct error code ERRDOS/ERRbadshare returned\n");
7412         }
7413
7414         status = cli_close(cli1, fnum1);
7415         if (!NT_STATUS_IS_OK(status)) {
7416                 printf("close2 failed (%s)\n", nt_errstr(status));
7417                 return False;
7418         }
7419
7420         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7421
7422         printf("finished open test 2\n");
7423
7424         /* Test truncate open disposition on file opened for read. */
7425         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7426         if (!NT_STATUS_IS_OK(status)) {
7427                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7428                 return False;
7429         }
7430
7431         /* write 20 bytes. */
7432
7433         memset(buf, '\0', 20);
7434
7435         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7436         if (!NT_STATUS_IS_OK(status)) {
7437                 printf("write failed (%s)\n", nt_errstr(status));
7438                 correct = False;
7439         }
7440
7441         status = cli_close(cli1, fnum1);
7442         if (!NT_STATUS_IS_OK(status)) {
7443                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7444                 return False;
7445         }
7446
7447         /* Ensure size == 20. */
7448         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7449         if (!NT_STATUS_IS_OK(status)) {
7450                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7451                 return False;
7452         }
7453
7454         if (fsize != 20) {
7455                 printf("(3) file size != 20\n");
7456                 return False;
7457         }
7458
7459         /* Now test if we can truncate a file opened for readonly. */
7460         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7461         if (!NT_STATUS_IS_OK(status)) {
7462                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7463                 return False;
7464         }
7465
7466         status = cli_close(cli1, fnum1);
7467         if (!NT_STATUS_IS_OK(status)) {
7468                 printf("close2 failed (%s)\n", nt_errstr(status));
7469                 return False;
7470         }
7471
7472         /* Ensure size == 0. */
7473         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7474         if (!NT_STATUS_IS_OK(status)) {
7475                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7476                 return False;
7477         }
7478
7479         if (fsize != 0) {
7480                 printf("(3) file size != 0\n");
7481                 return False;
7482         }
7483         printf("finished open test 3\n");
7484
7485         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7486
7487         printf("Do ctemp tests\n");
7488         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7489         if (!NT_STATUS_IS_OK(status)) {
7490                 printf("ctemp failed (%s)\n", nt_errstr(status));
7491                 return False;
7492         }
7493
7494         printf("ctemp gave path %s\n", tmp_path);
7495         status = cli_close(cli1, fnum1);
7496         if (!NT_STATUS_IS_OK(status)) {
7497                 printf("close of temp failed (%s)\n", nt_errstr(status));
7498         }
7499
7500         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7501         if (!NT_STATUS_IS_OK(status)) {
7502                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7503         }
7504
7505         /* Test the non-io opens... */
7506
7507         if (!torture_open_connection(&cli2, 1)) {
7508                 return False;
7509         }
7510
7511         cli_setatr(cli2, fname, 0, 0);
7512         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7513
7514         smbXcli_conn_set_sockopt(cli2->conn, sockops);
7515
7516         printf("TEST #1 testing 2 non-io opens (no delete)\n");
7517         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7518                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7519                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7520         if (!NT_STATUS_IS_OK(status)) {
7521                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7522                 return False;
7523         }
7524
7525         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7526                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7527                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7528         if (!NT_STATUS_IS_OK(status)) {
7529                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7530                 return False;
7531         }
7532
7533         status = cli_close(cli1, fnum1);
7534         if (!NT_STATUS_IS_OK(status)) {
7535                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7536                 return False;
7537         }
7538
7539         status = cli_close(cli2, fnum2);
7540         if (!NT_STATUS_IS_OK(status)) {
7541                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7542                 return False;
7543         }
7544
7545         printf("non-io open test #1 passed.\n");
7546
7547         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7548
7549         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7550
7551         status = cli_ntcreate(cli1, fname, 0,
7552                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7553                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7554                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7555         if (!NT_STATUS_IS_OK(status)) {
7556                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7557                 return False;
7558         }
7559
7560         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7561                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7562                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7563         if (!NT_STATUS_IS_OK(status)) {
7564                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7565                 return False;
7566         }
7567
7568         status = cli_close(cli1, fnum1);
7569         if (!NT_STATUS_IS_OK(status)) {
7570                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7571                 return False;
7572         }
7573
7574         status = cli_close(cli2, fnum2);
7575         if (!NT_STATUS_IS_OK(status)) {
7576                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7577                 return False;
7578         }
7579
7580         printf("non-io open test #2 passed.\n");
7581
7582         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7583
7584         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7585
7586         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7587                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7588                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7589         if (!NT_STATUS_IS_OK(status)) {
7590                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7591                 return False;
7592         }
7593
7594         status = cli_ntcreate(cli2, fname, 0,
7595                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7596                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7597                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7598         if (!NT_STATUS_IS_OK(status)) {
7599                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7600                 return False;
7601         }
7602
7603         status = cli_close(cli1, fnum1);
7604         if (!NT_STATUS_IS_OK(status)) {
7605                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7606                 return False;
7607         }
7608
7609         status = cli_close(cli2, fnum2);
7610         if (!NT_STATUS_IS_OK(status)) {
7611                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7612                 return False;
7613         }
7614
7615         printf("non-io open test #3 passed.\n");
7616
7617         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7618
7619         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7620
7621         status = cli_ntcreate(cli1, fname, 0,
7622                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7623                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7624                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7625         if (!NT_STATUS_IS_OK(status)) {
7626                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7627                 return False;
7628         }
7629
7630         status = cli_ntcreate(cli2, fname, 0,
7631                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7632                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7633                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7634         if (NT_STATUS_IS_OK(status)) {
7635                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7636                 return False;
7637         }
7638
7639         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7640
7641         status = cli_close(cli1, fnum1);
7642         if (!NT_STATUS_IS_OK(status)) {
7643                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7644                 return False;
7645         }
7646
7647         printf("non-io open test #4 passed.\n");
7648
7649         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7650
7651         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7652
7653         status = cli_ntcreate(cli1, fname, 0,
7654                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7655                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7656                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7657         if (!NT_STATUS_IS_OK(status)) {
7658                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7659                 return False;
7660         }
7661
7662         status = cli_ntcreate(cli2, fname, 0,
7663                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7664                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7665                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7666         if (!NT_STATUS_IS_OK(status)) {
7667                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7668                 return False;
7669         }
7670
7671         status = cli_close(cli1, fnum1);
7672         if (!NT_STATUS_IS_OK(status)) {
7673                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7674                 return False;
7675         }
7676
7677         status = cli_close(cli2, fnum2);
7678         if (!NT_STATUS_IS_OK(status)) {
7679                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7680                 return False;
7681         }
7682
7683         printf("non-io open test #5 passed.\n");
7684
7685         printf("TEST #6 testing 1 non-io open, one io open\n");
7686
7687         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7688
7689         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7690                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7691                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7692         if (!NT_STATUS_IS_OK(status)) {
7693                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7694                 return False;
7695         }
7696
7697         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7698                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7699                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7700         if (!NT_STATUS_IS_OK(status)) {
7701                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7702                 return False;
7703         }
7704
7705         status = cli_close(cli1, fnum1);
7706         if (!NT_STATUS_IS_OK(status)) {
7707                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7708                 return False;
7709         }
7710
7711         status = cli_close(cli2, fnum2);
7712         if (!NT_STATUS_IS_OK(status)) {
7713                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7714                 return False;
7715         }
7716
7717         printf("non-io open test #6 passed.\n");
7718
7719         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7720
7721         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7722
7723         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7724                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7725                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7726         if (!NT_STATUS_IS_OK(status)) {
7727                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7728                 return False;
7729         }
7730
7731         status = cli_ntcreate(cli2, fname, 0,
7732                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7733                               FILE_ATTRIBUTE_NORMAL,
7734                               FILE_SHARE_READ|FILE_SHARE_DELETE,
7735                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7736         if (NT_STATUS_IS_OK(status)) {
7737                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7738                 return False;
7739         }
7740
7741         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7742
7743         status = cli_close(cli1, fnum1);
7744         if (!NT_STATUS_IS_OK(status)) {
7745                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7746                 return False;
7747         }
7748
7749         printf("non-io open test #7 passed.\n");
7750
7751         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7752
7753         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7754         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7755                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7756                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7757         if (!NT_STATUS_IS_OK(status)) {
7758                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7759                 correct = false;
7760                 goto out;
7761         }
7762
7763         /* Write to ensure we have to update the file time. */
7764         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7765                               NULL);
7766         if (!NT_STATUS_IS_OK(status)) {
7767                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7768                 correct = false;
7769                 goto out;
7770         }
7771
7772         status = cli_close(cli1, fnum1);
7773         if (!NT_STATUS_IS_OK(status)) {
7774                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7775                 correct = false;
7776         }
7777
7778   out:
7779
7780         if (!torture_close_connection(cli1)) {
7781                 correct = False;
7782         }
7783         if (!torture_close_connection(cli2)) {
7784                 correct = False;
7785         }
7786
7787         return correct;
7788 }
7789
7790 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7791 {
7792         uint16_t major, minor;
7793         uint32_t caplow, caphigh;
7794         NTSTATUS status;
7795
7796         if (!SERVER_HAS_UNIX_CIFS(cli)) {
7797                 printf("Server doesn't support UNIX CIFS extensions.\n");
7798                 return NT_STATUS_NOT_SUPPORTED;
7799         }
7800
7801         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7802                                              &caphigh);
7803         if (!NT_STATUS_IS_OK(status)) {
7804                 printf("Server didn't return UNIX CIFS extensions: %s\n",
7805                        nt_errstr(status));
7806                 return status;
7807         }
7808
7809         status = cli_set_unix_extensions_capabilities(cli, major, minor,
7810                                                       caplow, caphigh);
7811         if (!NT_STATUS_IS_OK(status)) {
7812                 printf("Server doesn't support setting UNIX CIFS extensions: "
7813                        "%s.\n", nt_errstr(status));
7814                 return status;
7815         }
7816
7817         return NT_STATUS_OK;
7818 }
7819
7820 /*
7821   Test POSIX open /mkdir calls.
7822  */
7823 static bool run_simple_posix_open_test(int dummy)
7824 {
7825         static struct cli_state *cli1;
7826         const char *fname = "posix:file";
7827         const char *hname = "posix:hlink";
7828         const char *sname = "posix:symlink";
7829         const char *dname = "posix:dir";
7830         char buf[10];
7831         char *target = NULL;
7832         uint16_t fnum1 = (uint16_t)-1;
7833         SMB_STRUCT_STAT sbuf;
7834         bool correct = false;
7835         NTSTATUS status;
7836         size_t nread;
7837         const char *fname_windows = "windows_file";
7838         uint16_t fnum2 = (uint16_t)-1;
7839         bool ok;
7840
7841         printf("Starting simple POSIX open test\n");
7842
7843         if (!torture_open_connection(&cli1, 0)) {
7844                 return false;
7845         }
7846
7847         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7848
7849         status = torture_setup_unix_extensions(cli1);
7850         if (!NT_STATUS_IS_OK(status)) {
7851                 return false;
7852         }
7853
7854         cli_setatr(cli1, fname, 0, 0);
7855         cli_posix_unlink(cli1, fname);
7856         cli_setatr(cli1, dname, 0, 0);
7857         cli_posix_rmdir(cli1, dname);
7858         cli_setatr(cli1, hname, 0, 0);
7859         cli_posix_unlink(cli1, hname);
7860         cli_setatr(cli1, sname, 0, 0);
7861         cli_posix_unlink(cli1, sname);
7862         cli_setatr(cli1, fname_windows, 0, 0);
7863         cli_posix_unlink(cli1, fname_windows);
7864
7865         /* Create a directory. */
7866         status = cli_posix_mkdir(cli1, dname, 0777);
7867         if (!NT_STATUS_IS_OK(status)) {
7868                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7869                 goto out;
7870         }
7871
7872         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7873                                 0600, &fnum1);
7874         if (!NT_STATUS_IS_OK(status)) {
7875                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7876                 goto out;
7877         }
7878
7879         /* Test ftruncate - set file size. */
7880         status = cli_ftruncate(cli1, fnum1, 1000);
7881         if (!NT_STATUS_IS_OK(status)) {
7882                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7883                 goto out;
7884         }
7885
7886         /* Ensure st_size == 1000 */
7887         status = cli_posix_stat(cli1, fname, &sbuf);
7888         if (!NT_STATUS_IS_OK(status)) {
7889                 printf("stat failed (%s)\n", nt_errstr(status));
7890                 goto out;
7891         }
7892
7893         if (sbuf.st_ex_size != 1000) {
7894                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7895                 goto out;
7896         }
7897
7898         /* Ensure st_mode == 0600 */
7899         if ((sbuf.st_ex_mode & 07777) != 0600) {
7900                 printf("posix_open - bad permissions 0%o != 0600\n",
7901                                 (unsigned int)(sbuf.st_ex_mode & 07777));
7902                 goto out;
7903         }
7904
7905         /* Test ftruncate - set file size back to zero. */
7906         status = cli_ftruncate(cli1, fnum1, 0);
7907         if (!NT_STATUS_IS_OK(status)) {
7908                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7909                 goto out;
7910         }
7911
7912         status = cli_close(cli1, fnum1);
7913         if (!NT_STATUS_IS_OK(status)) {
7914                 printf("close failed (%s)\n", nt_errstr(status));
7915                 goto out;
7916         }
7917
7918         /* Now open the file again for read only. */
7919         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7920         if (!NT_STATUS_IS_OK(status)) {
7921                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7922                 goto out;
7923         }
7924
7925         /* Now unlink while open. */
7926         status = cli_posix_unlink(cli1, fname);
7927         if (!NT_STATUS_IS_OK(status)) {
7928                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7929                 goto out;
7930         }
7931
7932         status = cli_close(cli1, fnum1);
7933         if (!NT_STATUS_IS_OK(status)) {
7934                 printf("close(2) failed (%s)\n", nt_errstr(status));
7935                 goto out;
7936         }
7937
7938         /* Ensure the file has gone. */
7939         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7940         if (NT_STATUS_IS_OK(status)) {
7941                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7942                 goto out;
7943         }
7944
7945         /* Create again to test open with O_TRUNC. */
7946         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7947         if (!NT_STATUS_IS_OK(status)) {
7948                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7949                 goto out;
7950         }
7951
7952         /* Test ftruncate - set file size. */
7953         status = cli_ftruncate(cli1, fnum1, 1000);
7954         if (!NT_STATUS_IS_OK(status)) {
7955                 printf("ftruncate failed (%s)\n", nt_errstr(status));
7956                 goto out;
7957         }
7958
7959         /* Ensure st_size == 1000 */
7960         status = cli_posix_stat(cli1, fname, &sbuf);
7961         if (!NT_STATUS_IS_OK(status)) {
7962                 printf("stat failed (%s)\n", nt_errstr(status));
7963                 goto out;
7964         }
7965
7966         if (sbuf.st_ex_size != 1000) {
7967                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7968                 goto out;
7969         }
7970
7971         status = cli_close(cli1, fnum1);
7972         if (!NT_STATUS_IS_OK(status)) {
7973                 printf("close(2) failed (%s)\n", nt_errstr(status));
7974                 goto out;
7975         }
7976
7977         /* Re-open with O_TRUNC. */
7978         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7979         if (!NT_STATUS_IS_OK(status)) {
7980                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7981                 goto out;
7982         }
7983
7984         /* Ensure st_size == 0 */
7985         status = cli_posix_stat(cli1, fname, &sbuf);
7986         if (!NT_STATUS_IS_OK(status)) {
7987                 printf("stat failed (%s)\n", nt_errstr(status));
7988                 goto out;
7989         }
7990
7991         if (sbuf.st_ex_size != 0) {
7992                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7993                 goto out;
7994         }
7995
7996         status = cli_close(cli1, fnum1);
7997         if (!NT_STATUS_IS_OK(status)) {
7998                 printf("close failed (%s)\n", nt_errstr(status));
7999                 goto out;
8000         }
8001
8002         status = cli_posix_unlink(cli1, fname);
8003         if (!NT_STATUS_IS_OK(status)) {
8004                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8005                 goto out;
8006         }
8007
8008         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8009         if (!NT_STATUS_IS_OK(status)) {
8010                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8011                         dname, nt_errstr(status));
8012                 goto out;
8013         }
8014
8015         cli_close(cli1, fnum1);
8016
8017         /* What happens when we try and POSIX open a directory for write ? */
8018         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8019         if (NT_STATUS_IS_OK(status)) {
8020                 printf("POSIX open of directory %s succeeded, "
8021                        "should have failed.\n",
8022                        dname);
8023                 goto out;
8024         } else {
8025                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8026                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8027                         goto out;
8028                 }
8029         }
8030
8031         /* Create the file. */
8032         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8033                                 0600, &fnum1);
8034         if (!NT_STATUS_IS_OK(status)) {
8035                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8036                 goto out;
8037         }
8038
8039         /* Write some data into it. */
8040         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8041                               NULL);
8042         if (!NT_STATUS_IS_OK(status)) {
8043                 printf("cli_write failed: %s\n", nt_errstr(status));
8044                 goto out;
8045         }
8046
8047         cli_close(cli1, fnum1);
8048
8049         /* Now create a hardlink. */
8050         status = cli_posix_hardlink(cli1, fname, hname);
8051         if (!NT_STATUS_IS_OK(status)) {
8052                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8053                 goto out;
8054         }
8055
8056         /* Now create a symlink. */
8057         status = cli_posix_symlink(cli1, fname, sname);
8058         if (!NT_STATUS_IS_OK(status)) {
8059                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8060                 goto out;
8061         }
8062
8063         /* Open the hardlink for read. */
8064         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8065         if (!NT_STATUS_IS_OK(status)) {
8066                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8067                 goto out;
8068         }
8069
8070         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8071         if (!NT_STATUS_IS_OK(status)) {
8072                 printf("POSIX read of %s failed (%s)\n", hname,
8073                        nt_errstr(status));
8074                 goto out;
8075         } else if (nread != 10) {
8076                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8077                        hname, (unsigned long)nread, 10);
8078                 goto out;
8079         }
8080
8081         if (memcmp(buf, "TEST DATA\n", 10)) {
8082                 printf("invalid data read from hardlink\n");
8083                 goto out;
8084         }
8085
8086         /* Do a POSIX lock/unlock. */
8087         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8088         if (!NT_STATUS_IS_OK(status)) {
8089                 printf("POSIX lock failed %s\n", nt_errstr(status));
8090                 goto out;
8091         }
8092
8093         /* Punch a hole in the locked area. */
8094         status = cli_posix_unlock(cli1, fnum1, 10, 80);
8095         if (!NT_STATUS_IS_OK(status)) {
8096                 printf("POSIX unlock failed %s\n", nt_errstr(status));
8097                 goto out;
8098         }
8099
8100         cli_close(cli1, fnum1);
8101
8102         /* Open the symlink for read - this should fail. A POSIX
8103            client should not be doing opens on a symlink. */
8104         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8105         if (NT_STATUS_IS_OK(status)) {
8106                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8107                 goto out;
8108         }
8109         ok = check_both_error(
8110                 __LINE__, status, ERRDOS, ERRbadpath,
8111                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8112         if (!ok) {
8113                 printf("POSIX open of %s should have failed "
8114                        "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8115                        "failed with %s instead.\n",
8116                        sname, nt_errstr(status));
8117                 goto out;
8118         }
8119
8120         status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8121         if (!NT_STATUS_IS_OK(status)) {
8122                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8123                 goto out;
8124         }
8125
8126         if (strcmp(target, fname) != 0) {
8127                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8128                         sname, fname, target);
8129                 goto out;
8130         }
8131
8132         status = cli_posix_rmdir(cli1, dname);
8133         if (!NT_STATUS_IS_OK(status)) {
8134                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8135                 goto out;
8136         }
8137
8138         /* Check directory opens with a specific permission. */
8139         status = cli_posix_mkdir(cli1, dname, 0700);
8140         if (!NT_STATUS_IS_OK(status)) {
8141                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8142                 goto out;
8143         }
8144
8145         /* Ensure st_mode == 0700 */
8146         status = cli_posix_stat(cli1, dname, &sbuf);
8147         if (!NT_STATUS_IS_OK(status)) {
8148                 printf("stat failed (%s)\n", nt_errstr(status));
8149                 goto out;
8150         }
8151
8152         if ((sbuf.st_ex_mode & 07777) != 0700) {
8153                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8154                                 (unsigned int)(sbuf.st_ex_mode & 07777));
8155                 goto out;
8156         }
8157
8158         /*
8159          * Now create a Windows file, and attempt a POSIX unlink.
8160          * This should fail with a sharing violation but due to:
8161          *
8162          * [Bug 9571] Unlink after open causes smbd to panic
8163          *
8164          * ensure we've fixed the lock ordering violation.
8165          */
8166
8167         status = cli_ntcreate(cli1, fname_windows, 0,
8168                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
8169                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8170                         FILE_CREATE,
8171                         0x0, 0x0, &fnum2, NULL);
8172         if (!NT_STATUS_IS_OK(status)) {
8173                 printf("Windows create of %s failed (%s)\n", fname_windows,
8174                         nt_errstr(status));
8175                 goto out;
8176         }
8177
8178         /* Now try posix_unlink. */
8179         status = cli_posix_unlink(cli1, fname_windows);
8180         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8181                 printf("POSIX unlink of %s should fail "
8182                         "with NT_STATUS_SHARING_VIOLATION "
8183                         "got %s instead !\n",
8184                         fname_windows,
8185                         nt_errstr(status));
8186                 goto out;
8187         }
8188
8189         cli_close(cli1, fnum2);
8190
8191         printf("Simple POSIX open test passed\n");
8192         correct = true;
8193
8194   out:
8195
8196         if (fnum1 != (uint16_t)-1) {
8197                 cli_close(cli1, fnum1);
8198                 fnum1 = (uint16_t)-1;
8199         }
8200
8201         if (fnum2 != (uint16_t)-1) {
8202                 cli_close(cli1, fnum2);
8203                 fnum2 = (uint16_t)-1;
8204         }
8205
8206         cli_setatr(cli1, sname, 0, 0);
8207         cli_posix_unlink(cli1, sname);
8208         cli_setatr(cli1, hname, 0, 0);
8209         cli_posix_unlink(cli1, hname);
8210         cli_setatr(cli1, fname, 0, 0);
8211         cli_posix_unlink(cli1, fname);
8212         cli_setatr(cli1, dname, 0, 0);
8213         cli_posix_rmdir(cli1, dname);
8214         cli_setatr(cli1, fname_windows, 0, 0);
8215         cli_posix_unlink(cli1, fname_windows);
8216
8217         if (!torture_close_connection(cli1)) {
8218                 correct = false;
8219         }
8220
8221         return correct;
8222 }
8223
8224 /*
8225   Test POSIX and Windows ACLs are rejected on symlinks.
8226  */
8227 static bool run_acl_symlink_test(int dummy)
8228 {
8229         static struct cli_state *cli;
8230         const char *fname = "posix_file";
8231         const char *sname = "posix_symlink";
8232         uint16_t fnum = (uint16_t)-1;
8233         bool correct = false;
8234         NTSTATUS status;
8235         char *posix_acl = NULL;
8236         size_t posix_acl_len = 0;
8237         char *posix_acl_sym = NULL;
8238         size_t posix_acl_len_sym = 0;
8239         struct security_descriptor *sd = NULL;
8240         TALLOC_CTX *frame = NULL;
8241
8242         frame = talloc_stackframe();
8243
8244         printf("Starting acl symlink test\n");
8245
8246         if (!torture_open_connection(&cli, 0)) {
8247                 TALLOC_FREE(frame);
8248                 return false;
8249         }
8250
8251         smbXcli_conn_set_sockopt(cli->conn, sockops);
8252
8253         status = torture_setup_unix_extensions(cli);
8254         if (!NT_STATUS_IS_OK(status)) {
8255                 TALLOC_FREE(frame);
8256                 return false;
8257         }
8258
8259         cli_setatr(cli, fname, 0, 0);
8260         cli_posix_unlink(cli, fname);
8261         cli_setatr(cli, sname, 0, 0);
8262         cli_posix_unlink(cli, sname);
8263
8264         status = cli_ntcreate(cli,
8265                         fname,
8266                         0,
8267                         READ_CONTROL_ACCESS,
8268                         0,
8269                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8270                         FILE_CREATE,
8271                         0x0,
8272                         0x0,
8273                         &fnum,
8274                         NULL);
8275
8276         if (!NT_STATUS_IS_OK(status)) {
8277                 printf("cli_ntcreate of %s failed (%s)\n",
8278                         fname,
8279                         nt_errstr(status));
8280                 goto out;
8281         }
8282
8283         /* Get the Windows ACL on the file. */
8284         status = cli_query_secdesc(cli,
8285                                 fnum,
8286                                 frame,
8287                                 &sd);
8288         if (!NT_STATUS_IS_OK(status)) {
8289                 printf("cli_query_secdesc failed (%s)\n",
8290                         nt_errstr(status));
8291                 goto out;
8292         }
8293
8294         /* Get the POSIX ACL on the file. */
8295         status = cli_posix_getacl(cli,
8296                                 fname,
8297                                 frame,
8298                                 &posix_acl_len,
8299                                 &posix_acl);
8300
8301         if (!NT_STATUS_IS_OK(status)) {
8302                 printf("cli_posix_getacl failed (%s)\n",
8303                         nt_errstr(status));
8304                 goto out;
8305         }
8306
8307         status = cli_close(cli, fnum);
8308         if (!NT_STATUS_IS_OK(status)) {
8309                 printf("close failed (%s)\n", nt_errstr(status));
8310                 goto out;
8311         }
8312         fnum = (uint16_t)-1;
8313
8314         /* Now create a symlink. */
8315         status = cli_posix_symlink(cli, fname, sname);
8316         if (!NT_STATUS_IS_OK(status)) {
8317                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8318                         sname,
8319                         fname,
8320                         nt_errstr(status));
8321                 goto out;
8322         }
8323
8324         /* Open a handle on the symlink for SD set/get should fail. */
8325         status = cli_ntcreate(cli,
8326                         sname,
8327                         0,
8328                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8329                         0,
8330                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8331                         FILE_OPEN,
8332                         0x0,
8333                         0x0,
8334                         &fnum,
8335                         NULL);
8336
8337         if (NT_STATUS_IS_OK(status)) {
8338                 printf("Symlink open for getsd/setsd of %s "
8339                         "succeeded (should fail)\n",
8340                         sname);
8341                 goto out;
8342         }
8343
8344         /* Try a stat-open on the symlink, should also fail. */
8345         status = cli_ntcreate(cli,
8346                         sname,
8347                         0,
8348                         FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8349                         0,
8350                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8351                         FILE_OPEN,
8352                         0x0,
8353                         0x0,
8354                         &fnum,
8355                         NULL);
8356
8357         if (NT_STATUS_IS_OK(status)) {
8358                 printf("Stat-open of symlink succeeded (should fail)\n");
8359                 goto out;
8360         }
8361
8362         /* Get the POSIX ACL on the symlink pathname. Should fail. */
8363         status = cli_posix_getacl(cli,
8364                                 sname,
8365                                 frame,
8366                                 &posix_acl_len_sym,
8367                                 &posix_acl_sym);
8368
8369         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8370                 printf("cli_posix_getacl on a symlink gave %s. "
8371                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8372                         nt_errstr(status));
8373                 goto out;
8374         }
8375
8376         /* Set the POSIX ACL on the symlink pathname. Should fail. */
8377         status = cli_posix_setacl(cli,
8378                                 sname,
8379                                 posix_acl,
8380                                 posix_acl_len);
8381
8382         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8383                 printf("cli_posix_setacl on a symlink gave %s. "
8384                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8385                         nt_errstr(status));
8386                 goto out;
8387         }
8388
8389         printf("ACL symlink test passed\n");
8390         correct = true;
8391
8392   out:
8393
8394         if (fnum != (uint16_t)-1) {
8395                 cli_close(cli, fnum);
8396                 fnum = (uint16_t)-1;
8397         }
8398
8399         cli_setatr(cli, sname, 0, 0);
8400         cli_posix_unlink(cli, sname);
8401         cli_setatr(cli, fname, 0, 0);
8402         cli_posix_unlink(cli, fname);
8403
8404         if (!torture_close_connection(cli)) {
8405                 correct = false;
8406         }
8407
8408         TALLOC_FREE(frame);
8409         return correct;
8410 }
8411
8412 /*
8413   Test POSIX can delete a file containing streams.
8414  */
8415 static bool run_posix_stream_delete(int dummy)
8416 {
8417         struct cli_state *cli1 = NULL;
8418         struct cli_state *cli2 = NULL;
8419         const char *fname = "streamfile";
8420         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8421         uint16_t fnum1 = (uint16_t)-1;
8422         bool correct = false;
8423         NTSTATUS status;
8424         TALLOC_CTX *frame = NULL;
8425
8426         frame = talloc_stackframe();
8427
8428         printf("Starting POSIX stream delete test\n");
8429
8430         if (!torture_open_connection(&cli1, 0) ||
8431                         !torture_open_connection(&cli2, 1)) {
8432                 TALLOC_FREE(frame);
8433                 return false;
8434         }
8435
8436         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8437         smbXcli_conn_set_sockopt(cli2->conn, sockops);
8438
8439         status = torture_setup_unix_extensions(cli2);
8440         if (!NT_STATUS_IS_OK(status)) {
8441                 goto out;
8442         }
8443
8444         cli_setatr(cli1, fname, 0, 0);
8445         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8446
8447         /* Create the file. */
8448         status = cli_ntcreate(cli1,
8449                         fname,
8450                         0,
8451                         READ_CONTROL_ACCESS,
8452                         0,
8453                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8454                         FILE_CREATE,
8455                         0x0,
8456                         0x0,
8457                         &fnum1,
8458                         NULL);
8459
8460         if (!NT_STATUS_IS_OK(status)) {
8461                 printf("cli_ntcreate of %s failed (%s)\n",
8462                         fname,
8463                         nt_errstr(status));
8464                 goto out;
8465         }
8466
8467         status = cli_close(cli1, fnum1);
8468         if (!NT_STATUS_IS_OK(status)) {
8469                 printf("cli_close of %s failed (%s)\n",
8470                         fname,
8471                         nt_errstr(status));
8472                 goto out;
8473         }
8474         fnum1 = (uint16_t)-1;
8475
8476         /* Now create the stream. */
8477         status = cli_ntcreate(cli1,
8478                         stream_fname,
8479                         0,
8480                         FILE_WRITE_DATA,
8481                         0,
8482                         FILE_SHARE_READ|FILE_SHARE_WRITE,
8483                         FILE_CREATE,
8484                         0x0,
8485                         0x0,
8486                         &fnum1,
8487                         NULL);
8488
8489         if (!NT_STATUS_IS_OK(status)) {
8490                 printf("cli_ntcreate of %s failed (%s)\n",
8491                         stream_fname,
8492                         nt_errstr(status));
8493                 goto out;
8494         }
8495
8496         /* Leave the stream handle open... */
8497
8498         /* POSIX unlink should fail. */
8499         status = cli_posix_unlink(cli2, fname);
8500         if (NT_STATUS_IS_OK(status)) {
8501                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8502                         fname);
8503                 goto out;
8504         }
8505
8506         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8507                 printf("cli_posix_unlink of %s failed with (%s) "
8508                         "should have been NT_STATUS_SHARING_VIOLATION\n",
8509                         fname,
8510                         nt_errstr(status));
8511                 goto out;
8512         }
8513
8514         /* Close the stream handle. */
8515         status = cli_close(cli1, fnum1);
8516         if (!NT_STATUS_IS_OK(status)) {
8517                 printf("cli_close of %s failed (%s)\n",
8518                         stream_fname,
8519                         nt_errstr(status));
8520                 goto out;
8521         }
8522         fnum1 = (uint16_t)-1;
8523
8524         /* POSIX unlink after stream handle closed should succeed. */
8525         status = cli_posix_unlink(cli2, fname);
8526         if (!NT_STATUS_IS_OK(status)) {
8527                 printf("cli_posix_unlink of %s failed (%s)\n",
8528                         fname,
8529                         nt_errstr(status));
8530                 goto out;
8531         }
8532
8533         printf("POSIX stream delete test passed\n");
8534         correct = true;
8535
8536   out:
8537
8538         if (fnum1 != (uint16_t)-1) {
8539                 cli_close(cli1, fnum1);
8540                 fnum1 = (uint16_t)-1;
8541         }
8542
8543         cli_setatr(cli1, fname, 0, 0);
8544         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8545
8546         if (!torture_close_connection(cli1)) {
8547                 correct = false;
8548         }
8549         if (!torture_close_connection(cli2)) {
8550                 correct = false;
8551         }
8552
8553         TALLOC_FREE(frame);
8554         return correct;
8555 }
8556
8557 /*
8558   Test setting EA's are rejected on symlinks.
8559  */
8560 static bool run_ea_symlink_test(int dummy)
8561 {
8562         static struct cli_state *cli;
8563         const char *fname = "posix_file_ea";
8564         const char *sname = "posix_symlink_ea";
8565         const char *ea_name = "testea_name";
8566         const char *ea_value = "testea_value";
8567         uint16_t fnum = (uint16_t)-1;
8568         bool correct = false;
8569         NTSTATUS status;
8570         size_t i, num_eas;
8571         struct ea_struct *eas = NULL;
8572         TALLOC_CTX *frame = NULL;
8573
8574         frame = talloc_stackframe();
8575
8576         printf("Starting EA symlink test\n");
8577
8578         if (!torture_open_connection(&cli, 0)) {
8579                 TALLOC_FREE(frame);
8580                 return false;
8581         }
8582
8583         smbXcli_conn_set_sockopt(cli->conn, sockops);
8584
8585         status = torture_setup_unix_extensions(cli);
8586         if (!NT_STATUS_IS_OK(status)) {
8587                 TALLOC_FREE(frame);
8588                 return false;
8589         }
8590
8591         cli_setatr(cli, fname, 0, 0);
8592         cli_posix_unlink(cli, fname);
8593         cli_setatr(cli, sname, 0, 0);
8594         cli_posix_unlink(cli, sname);
8595
8596         status = cli_ntcreate(cli,
8597                         fname,
8598                         0,
8599                         READ_CONTROL_ACCESS,
8600                         0,
8601                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8602                         FILE_CREATE,
8603                         0x0,
8604                         0x0,
8605                         &fnum,
8606                         NULL);
8607
8608         if (!NT_STATUS_IS_OK(status)) {
8609                 printf("cli_ntcreate of %s failed (%s)\n",
8610                         fname,
8611                         nt_errstr(status));
8612                 goto out;
8613         }
8614
8615         status = cli_close(cli, fnum);
8616         if (!NT_STATUS_IS_OK(status)) {
8617                 printf("close failed (%s)\n",
8618                         nt_errstr(status));
8619                 goto out;
8620         }
8621         fnum = (uint16_t)-1;
8622
8623         /* Set an EA on the path. */
8624         status = cli_set_ea_path(cli,
8625                                 fname,
8626                                 ea_name,
8627                                 ea_value,
8628                                 strlen(ea_value)+1);
8629
8630         if (!NT_STATUS_IS_OK(status)) {
8631                 printf("cli_set_ea_path failed (%s)\n",
8632                         nt_errstr(status));
8633                 goto out;
8634         }
8635
8636         /* Now create a symlink. */
8637         status = cli_posix_symlink(cli, fname, sname);
8638         if (!NT_STATUS_IS_OK(status)) {
8639                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8640                         sname,
8641                         fname,
8642                         nt_errstr(status));
8643                 goto out;
8644         }
8645
8646         /* Get the EA list on the path. Should return value set. */
8647         status = cli_get_ea_list_path(cli,
8648                                 fname,
8649                                 frame,
8650                                 &num_eas,
8651                                 &eas);
8652
8653         if (!NT_STATUS_IS_OK(status)) {
8654                 printf("cli_get_ea_list_path failed (%s)\n",
8655                         nt_errstr(status));
8656                 goto out;
8657         }
8658
8659         /* Ensure the EA we set is there. */
8660         for (i=0; i<num_eas; i++) {
8661                 if (strcmp(eas[i].name, ea_name) == 0 &&
8662                                 eas[i].value.length == strlen(ea_value)+1 &&
8663                                 memcmp(eas[i].value.data,
8664                                         ea_value,
8665                                         eas[i].value.length) == 0) {
8666                         break;
8667                 }
8668         }
8669
8670         if (i == num_eas) {
8671                 printf("Didn't find EA on pathname %s\n",
8672                         fname);
8673                 goto out;
8674         }
8675
8676         num_eas = 0;
8677         TALLOC_FREE(eas);
8678
8679         /* Get the EA list on the symlink. Should return empty list. */
8680         status = cli_get_ea_list_path(cli,
8681                                 sname,
8682                                 frame,
8683                                 &num_eas,
8684                                 &eas);
8685
8686         if (!NT_STATUS_IS_OK(status)) {
8687                 printf("cli_get_ea_list_path failed (%s)\n",
8688                         nt_errstr(status));
8689                 goto out;
8690         }
8691
8692         if (num_eas != 0) {
8693                 printf("cli_get_ea_list_path failed (%s)\n",
8694                         nt_errstr(status));
8695                 goto out;
8696         }
8697
8698         /* Set an EA on the symlink. Should fail. */
8699         status = cli_set_ea_path(cli,
8700                                 sname,
8701                                 ea_name,
8702                                 ea_value,
8703                                 strlen(ea_value)+1);
8704
8705         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8706                 printf("cli_set_ea_path on a symlink gave %s. "
8707                         "Should be NT_STATUS_ACCESS_DENIED.\n",
8708                         nt_errstr(status));
8709                 goto out;
8710         }
8711
8712         printf("EA symlink test passed\n");
8713         correct = true;
8714
8715   out:
8716
8717         if (fnum != (uint16_t)-1) {
8718                 cli_close(cli, fnum);
8719                 fnum = (uint16_t)-1;
8720         }
8721
8722         cli_setatr(cli, sname, 0, 0);
8723         cli_posix_unlink(cli, sname);
8724         cli_setatr(cli, fname, 0, 0);
8725         cli_posix_unlink(cli, fname);
8726
8727         if (!torture_close_connection(cli)) {
8728                 correct = false;
8729         }
8730
8731         TALLOC_FREE(frame);
8732         return correct;
8733 }
8734
8735 /*
8736   Test POSIX locks are OFD-locks.
8737  */
8738 static bool run_posix_ofd_lock_test(int dummy)
8739 {
8740         static struct cli_state *cli;
8741         const char *fname = "posix_file";
8742         uint16_t fnum1 = (uint16_t)-1;
8743         uint16_t fnum2 = (uint16_t)-1;
8744         bool correct = false;
8745         NTSTATUS status;
8746         TALLOC_CTX *frame = NULL;
8747
8748         frame = talloc_stackframe();
8749
8750         printf("Starting POSIX ofd-lock test\n");
8751
8752         if (!torture_open_connection(&cli, 0)) {
8753                 TALLOC_FREE(frame);
8754                 return false;
8755         }
8756
8757         smbXcli_conn_set_sockopt(cli->conn, sockops);
8758
8759         status = torture_setup_unix_extensions(cli);
8760         if (!NT_STATUS_IS_OK(status)) {
8761                 TALLOC_FREE(frame);
8762                 return false;
8763         }
8764
8765         cli_setatr(cli, fname, 0, 0);
8766         cli_posix_unlink(cli, fname);
8767
8768         /* Open the file twice. */
8769         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8770                                 0600, &fnum1);
8771         if (!NT_STATUS_IS_OK(status)) {
8772                 printf("First POSIX open of %s failed\n", fname);
8773                 goto out;
8774         }
8775
8776         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8777         if (!NT_STATUS_IS_OK(status)) {
8778                 printf("First POSIX open of %s failed\n", fname);
8779                 goto out;
8780         }
8781
8782         /* Set a 0-50 lock on fnum1. */
8783         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8784         if (!NT_STATUS_IS_OK(status)) {
8785                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8786                 goto out;
8787         }
8788
8789         /* Set a 60-100 lock on fnum2. */
8790         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8791         if (!NT_STATUS_IS_OK(status)) {
8792                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8793                 goto out;
8794         }
8795
8796         /* close fnum1 - 0-50 lock should go away. */
8797         status = cli_close(cli, fnum1);
8798         if (!NT_STATUS_IS_OK(status)) {
8799                 printf("close failed (%s)\n",
8800                         nt_errstr(status));
8801                 goto out;
8802         }
8803         fnum1 = (uint16_t)-1;
8804
8805         /* Change the lock context. */
8806         cli_setpid(cli, cli_getpid(cli) + 1);
8807
8808         /* Re-open fnum1. */
8809         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8810         if (!NT_STATUS_IS_OK(status)) {
8811                 printf("Third POSIX open of %s failed\n", fname);
8812                 goto out;
8813         }
8814
8815         /* 60-100 lock should still be there. */
8816         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8817         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8818                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8819                 goto out;
8820         }
8821
8822         /* 0-50 lock should be gone. */
8823         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8824         if (!NT_STATUS_IS_OK(status)) {
8825                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8826                 goto out;
8827         }
8828
8829         printf("POSIX OFD lock test passed\n");
8830         correct = true;
8831
8832   out:
8833
8834         if (fnum1 != (uint16_t)-1) {
8835                 cli_close(cli, fnum1);
8836                 fnum1 = (uint16_t)-1;
8837         }
8838         if (fnum2 != (uint16_t)-1) {
8839                 cli_close(cli, fnum2);
8840                 fnum2 = (uint16_t)-1;
8841         }
8842
8843         cli_setatr(cli, fname, 0, 0);
8844         cli_posix_unlink(cli, fname);
8845
8846         if (!torture_close_connection(cli)) {
8847                 correct = false;
8848         }
8849
8850         TALLOC_FREE(frame);
8851         return correct;
8852 }
8853
8854 struct posix_blocking_state {
8855         struct tevent_context *ev;
8856         struct cli_state *cli1;
8857         uint16_t fnum1;
8858         struct cli_state *cli2;
8859         uint16_t fnum2;
8860         bool gotblocked;
8861         bool gotecho;
8862 };
8863
8864 static void posix_blocking_locked(struct tevent_req *subreq);
8865 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8866 static void posix_blocking_gotecho(struct tevent_req *subreq);
8867 static void posix_blocking_unlocked(struct tevent_req *subreq);
8868
8869 static struct tevent_req *posix_blocking_send(
8870         TALLOC_CTX *mem_ctx,
8871         struct tevent_context *ev,
8872         struct cli_state *cli1,
8873         uint16_t fnum1,
8874         struct cli_state *cli2,
8875         uint16_t fnum2)
8876 {
8877         struct tevent_req *req = NULL, *subreq = NULL;
8878         struct posix_blocking_state *state = NULL;
8879
8880         req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8881         if (req == NULL) {
8882                 return NULL;
8883         }
8884         state->ev = ev;
8885         state->cli1 = cli1;
8886         state->fnum1 = fnum1;
8887         state->cli2 = cli2;
8888         state->fnum2 = fnum2;
8889
8890         subreq = cli_posix_lock_send(
8891                 state,
8892                 state->ev,
8893                 state->cli1,
8894                 state->fnum1,
8895                 0,
8896                 1,
8897                 false,
8898                 WRITE_LOCK);
8899         if (tevent_req_nomem(subreq, req)) {
8900                 return tevent_req_post(req, ev);
8901         }
8902         tevent_req_set_callback(subreq, posix_blocking_locked, req);
8903         return req;
8904 }
8905
8906 static void posix_blocking_locked(struct tevent_req *subreq)
8907 {
8908         struct tevent_req *req = tevent_req_callback_data(
8909                 subreq, struct tevent_req);
8910         struct posix_blocking_state *state = tevent_req_data(
8911                 req, struct posix_blocking_state);
8912         NTSTATUS status;
8913
8914         status = cli_posix_lock_recv(subreq);
8915         TALLOC_FREE(subreq);
8916         if (tevent_req_nterror(req, status)) {
8917                 return;
8918         }
8919
8920         subreq = cli_posix_lock_send(
8921                 state,
8922                 state->ev,
8923                 state->cli2,
8924                 state->fnum2,
8925                 0,
8926                 1,
8927                 true,
8928                 WRITE_LOCK);
8929         if (tevent_req_nomem(subreq, req)) {
8930                 return;
8931         }
8932         tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8933
8934         /* Make sure the blocking request is delivered */
8935         subreq = cli_echo_send(
8936                 state,
8937                 state->ev,
8938                 state->cli2,
8939                 1,
8940                 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8941         if (tevent_req_nomem(subreq, req)) {
8942                 return;
8943         }
8944         tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8945 }
8946
8947 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8948 {
8949         struct tevent_req *req = tevent_req_callback_data(
8950                 subreq, struct tevent_req);
8951         struct posix_blocking_state *state = tevent_req_data(
8952                 req, struct posix_blocking_state);
8953         NTSTATUS status;
8954
8955         status = cli_posix_lock_recv(subreq);
8956         TALLOC_FREE(subreq);
8957         if (tevent_req_nterror(req, status)) {
8958                 return;
8959         }
8960         if (!state->gotecho) {
8961                 printf("blocked req got through before echo\n");
8962                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8963                 return;
8964         }
8965         tevent_req_done(req);
8966 }
8967
8968 static void posix_blocking_gotecho(struct tevent_req *subreq)
8969 {
8970         struct tevent_req *req = tevent_req_callback_data(
8971                 subreq, struct tevent_req);
8972         struct posix_blocking_state *state = tevent_req_data(
8973                 req, struct posix_blocking_state);
8974         NTSTATUS status;
8975
8976         status = cli_echo_recv(subreq);
8977         TALLOC_FREE(subreq);
8978         if (tevent_req_nterror(req, status)) {
8979                 return;
8980         }
8981         if (state->gotblocked) {
8982                 printf("blocked req got through before echo\n");
8983                 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8984                 return;
8985         }
8986         state->gotecho = true;
8987
8988         subreq = cli_posix_lock_send(
8989                 state,
8990                 state->ev,
8991                 state->cli1,
8992                 state->fnum1,
8993                 0,
8994                 1,
8995                 false,
8996                 UNLOCK_LOCK);
8997         if (tevent_req_nomem(subreq, req)) {
8998                 return;
8999         }
9000         tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9001 }
9002
9003 static void posix_blocking_unlocked(struct tevent_req *subreq)
9004 {
9005         struct tevent_req *req = tevent_req_callback_data(
9006                 subreq, struct tevent_req);
9007         NTSTATUS status;
9008
9009         status = cli_posix_lock_recv(subreq);
9010         TALLOC_FREE(subreq);
9011         if (tevent_req_nterror(req, status)) {
9012                 return;
9013         }
9014         /* tevent_req_done in posix_blocking_gotlocked */
9015 }
9016
9017 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9018 {
9019         return tevent_req_simple_recv_ntstatus(req);
9020 }
9021
9022 static bool run_posix_blocking_lock(int dummy)
9023 {
9024         struct tevent_context *ev = NULL;
9025         struct cli_state *cli1 = NULL, *cli2 = NULL;
9026         const char *fname = "posix_blocking";
9027         uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9028         struct tevent_req *req = NULL;
9029         NTSTATUS status;
9030         bool ret = false;
9031         bool ok;
9032
9033         printf("Starting posix blocking lock test\n");
9034
9035         ev = samba_tevent_context_init(NULL);
9036         if (ev == NULL) {
9037                 return false;
9038         }
9039
9040         ok = torture_open_connection(&cli1, 0);
9041         if (!ok) {
9042                 goto fail;
9043         }
9044         ok = torture_open_connection(&cli2, 0);
9045         if (!ok) {
9046                 goto fail;
9047         }
9048
9049         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9050
9051         status = torture_setup_unix_extensions(cli1);
9052         if (!NT_STATUS_IS_OK(status)) {
9053                 return false;
9054         }
9055
9056         status = torture_setup_unix_extensions(cli2);
9057         if (!NT_STATUS_IS_OK(status)) {
9058                 return false;
9059         }
9060
9061         cli_setatr(cli1, fname, 0, 0);
9062         cli_posix_unlink(cli1, fname);
9063
9064         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9065                                 0600, &fnum1);
9066         if (!NT_STATUS_IS_OK(status)) {
9067                 printf("First POSIX open of %s failed: %s\n",
9068                        fname,
9069                        nt_errstr(status));
9070                 goto fail;
9071         }
9072
9073         status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9074         if (!NT_STATUS_IS_OK(status)) {
9075                 printf("Second POSIX open of %s failed: %s\n",
9076                        fname,
9077                        nt_errstr(status));
9078                 goto fail;
9079         }
9080
9081         req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9082         if (req == NULL) {
9083                 printf("cli_posix_blocking failed\n");
9084                 goto fail;
9085         }
9086
9087         ok = tevent_req_poll_ntstatus(req, ev, &status);
9088         if (!ok) {
9089                 printf("tevent_req_poll_ntstatus failed: %s\n",
9090                        nt_errstr(status));
9091                 goto fail;
9092         }
9093         status = posix_blocking_recv(req);
9094         TALLOC_FREE(req);
9095         if (!NT_STATUS_IS_OK(status)) {
9096                 printf("posix_blocking_recv returned %s\n",
9097                        nt_errstr(status));
9098                 goto fail;
9099         }
9100
9101         ret = true;
9102 fail:
9103
9104         if (fnum1 != UINT16_MAX) {
9105                 cli_close(cli1, fnum1);
9106                 fnum1 = UINT16_MAX;
9107         }
9108         if (fnum2 != UINT16_MAX) {
9109                 cli_close(cli2, fnum2);
9110                 fnum2 = UINT16_MAX;
9111         }
9112
9113         if (cli1 != NULL) {
9114                 cli_setatr(cli1, fname, 0, 0);
9115                 cli_posix_unlink(cli1, fname);
9116         }
9117
9118         ok = true;
9119
9120         if (cli1 != NULL) {
9121                 ok &= torture_close_connection(cli1);
9122                 cli1 = NULL;
9123         }
9124         if (cli2 != NULL) {
9125                 ok &= torture_close_connection(cli2);
9126                 cli2 = NULL;
9127         }
9128
9129         if (!ok) {
9130                 ret = false;
9131         }
9132         TALLOC_FREE(ev);
9133         return ret;
9134 }
9135
9136 /*
9137   Test POSIX mkdir is case-sensitive.
9138  */
9139 static bool run_posix_mkdir_test(int dummy)
9140 {
9141         static struct cli_state *cli;
9142         const char *fname_foo = "POSIX_foo";
9143         const char *fname_foo_Foo = "POSIX_foo/Foo";
9144         const char *fname_foo_foo = "POSIX_foo/foo";
9145         const char *fname_Foo = "POSIX_Foo";
9146         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9147         const char *fname_Foo_foo = "POSIX_Foo/foo";
9148         bool correct = false;
9149         NTSTATUS status;
9150         TALLOC_CTX *frame = NULL;
9151         uint16_t fnum = (uint16_t)-1;
9152
9153         frame = talloc_stackframe();
9154
9155         printf("Starting POSIX mkdir test\n");
9156
9157         if (!torture_open_connection(&cli, 0)) {
9158                 TALLOC_FREE(frame);
9159                 return false;
9160         }
9161
9162         smbXcli_conn_set_sockopt(cli->conn, sockops);
9163
9164         status = torture_setup_unix_extensions(cli);
9165         if (!NT_STATUS_IS_OK(status)) {
9166                 TALLOC_FREE(frame);
9167                 return false;
9168         }
9169
9170         cli_posix_rmdir(cli, fname_foo_foo);
9171         cli_posix_rmdir(cli, fname_foo_Foo);
9172         cli_posix_rmdir(cli, fname_foo);
9173
9174         cli_posix_rmdir(cli, fname_Foo_foo);
9175         cli_posix_rmdir(cli, fname_Foo_Foo);
9176         cli_posix_rmdir(cli, fname_Foo);
9177
9178         /*
9179          * Create a file POSIX_foo then try
9180          * and use it in a directory path by
9181          * doing mkdir POSIX_foo/bar.
9182          * The mkdir should fail with
9183          * NT_STATUS_OBJECT_PATH_NOT_FOUND
9184          */
9185
9186         status = cli_posix_open(cli,
9187                         fname_foo,
9188                         O_RDWR|O_CREAT,
9189                         0666,
9190                         &fnum);
9191         if (!NT_STATUS_IS_OK(status)) {
9192                 printf("cli_posix_open of %s failed error %s\n",
9193                         fname_foo,
9194                         nt_errstr(status));
9195                 goto out;
9196         }
9197
9198         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9199         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9200                 printf("cli_posix_mkdir of %s should fail with "
9201                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9202                         "%s instead\n",
9203                         fname_foo_foo,
9204                         nt_errstr(status));
9205                 goto out;
9206         }
9207
9208         status = cli_close(cli, fnum);
9209         if (!NT_STATUS_IS_OK(status)) {
9210                 printf("cli_close failed %s\n", nt_errstr(status));
9211                 goto out;
9212         }
9213         fnum = (uint16_t)-1;
9214
9215         status = cli_posix_unlink(cli, fname_foo);
9216         if (!NT_STATUS_IS_OK(status)) {
9217                 printf("cli_posix_unlink of %s failed error %s\n",
9218                         fname_foo,
9219                         nt_errstr(status));
9220                 goto out;
9221         }
9222
9223         /*
9224          * Now we've deleted everything, posix_mkdir, posix_rmdir,
9225          * posix_open, posix_unlink, on
9226          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9227          * not silently create POSIX_foo/foo.
9228          */
9229
9230         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9231         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9232                 printf("cli_posix_mkdir of %s should fail with "
9233                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9234                         "%s instead\n",
9235                         fname_foo_foo,
9236                         nt_errstr(status));
9237                 goto out;
9238         }
9239
9240         status = cli_posix_rmdir(cli, fname_foo_foo);
9241         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9242                 printf("cli_posix_rmdir of %s should fail with "
9243                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9244                         "%s instead\n",
9245                         fname_foo_foo,
9246                         nt_errstr(status));
9247                 goto out;
9248         }
9249
9250         status = cli_posix_open(cli,
9251                         fname_foo_foo,
9252                         O_RDWR|O_CREAT,
9253                         0666,
9254                         &fnum);
9255         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9256                 printf("cli_posix_open of %s should fail with "
9257                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9258                         "%s instead\n",
9259                         fname_foo_foo,
9260                         nt_errstr(status));
9261                 goto out;
9262         }
9263
9264         status = cli_posix_unlink(cli, fname_foo_foo);
9265         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9266                 printf("cli_posix_unlink of %s should fail with "
9267                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9268                         "%s instead\n",
9269                         fname_foo_foo,
9270                         nt_errstr(status));
9271                 goto out;
9272         }
9273
9274         status = cli_posix_mkdir(cli, fname_foo, 0777);
9275         if (!NT_STATUS_IS_OK(status)) {
9276                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9277                 goto out;
9278         }
9279
9280         status = cli_posix_mkdir(cli, fname_Foo, 0777);
9281         if (!NT_STATUS_IS_OK(status)) {
9282                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9283                 goto out;
9284         }
9285
9286         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9287         if (!NT_STATUS_IS_OK(status)) {
9288                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9289                 goto out;
9290         }
9291
9292         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9293         if (!NT_STATUS_IS_OK(status)) {
9294                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9295                 goto out;
9296         }
9297
9298         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9299         if (!NT_STATUS_IS_OK(status)) {
9300                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9301                 goto out;
9302         }
9303
9304         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9305         if (!NT_STATUS_IS_OK(status)) {
9306                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9307                 goto out;
9308         }
9309
9310         printf("POSIX mkdir test passed\n");
9311         correct = true;
9312
9313   out:
9314
9315         if (fnum != (uint16_t)-1) {
9316                 cli_close(cli, fnum);
9317                 fnum = (uint16_t)-1;
9318         }
9319
9320         cli_posix_rmdir(cli, fname_foo_foo);
9321         cli_posix_rmdir(cli, fname_foo_Foo);
9322         cli_posix_rmdir(cli, fname_foo);
9323
9324         cli_posix_rmdir(cli, fname_Foo_foo);
9325         cli_posix_rmdir(cli, fname_Foo_Foo);
9326         cli_posix_rmdir(cli, fname_Foo);
9327
9328         if (!torture_close_connection(cli)) {
9329                 correct = false;
9330         }
9331
9332         TALLOC_FREE(frame);
9333         return correct;
9334 }
9335
9336 struct posix_acl_oplock_state {
9337         struct tevent_context *ev;
9338         struct cli_state *cli;
9339         bool *got_break;
9340         bool *acl_ret;
9341         NTSTATUS status;
9342 };
9343
9344 static void posix_acl_oplock_got_break(struct tevent_req *req)
9345 {
9346         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9347                 req, struct posix_acl_oplock_state);
9348         uint16_t fnum;
9349         uint8_t level;
9350         NTSTATUS status;
9351
9352         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9353         TALLOC_FREE(req);
9354         if (!NT_STATUS_IS_OK(status)) {
9355                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9356                        nt_errstr(status));
9357                 return;
9358         }
9359         *state->got_break = true;
9360
9361         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9362                                   NO_OPLOCK);
9363         if (req == NULL) {
9364                 printf("cli_oplock_ack_send failed\n");
9365                 return;
9366         }
9367 }
9368
9369 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9370 {
9371         struct posix_acl_oplock_state *state = tevent_req_callback_data(
9372                 req, struct posix_acl_oplock_state);
9373         size_t ret_size = 0;
9374         char *ret_data = NULL;
9375
9376         state->status = cli_posix_getacl_recv(req,
9377                         state,
9378                         &ret_size,
9379                         &ret_data);
9380
9381         if (!NT_STATUS_IS_OK(state->status)) {
9382                 printf("cli_posix_getacl_recv returned %s\n",
9383                         nt_errstr(state->status));
9384         }
9385         *state->acl_ret = true;
9386 }
9387
9388 static bool run_posix_acl_oplock_test(int dummy)
9389 {
9390         struct tevent_context *ev;
9391         struct cli_state *cli1, *cli2;
9392         struct tevent_req *oplock_req, *getacl_req;
9393         const char *fname = "posix_acl_oplock";
9394         uint16_t fnum;
9395         int saved_use_oplocks = use_oplocks;
9396         NTSTATUS status;
9397         bool correct = true;
9398         bool got_break = false;
9399         bool acl_ret = false;
9400
9401         struct posix_acl_oplock_state *state;
9402
9403         printf("starting posix_acl_oplock test\n");
9404
9405         if (!torture_open_connection(&cli1, 0)) {
9406                 use_level_II_oplocks = false;
9407                 use_oplocks = saved_use_oplocks;
9408                 return false;
9409         }
9410
9411         if (!torture_open_connection(&cli2, 1)) {
9412                 use_level_II_oplocks = false;
9413                 use_oplocks = saved_use_oplocks;
9414                 return false;
9415         }
9416
9417         /* Setup posix on cli2 only. */
9418         status = torture_setup_unix_extensions(cli2);
9419         if (!NT_STATUS_IS_OK(status)) {
9420                 return false;
9421         }
9422
9423         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9424         smbXcli_conn_set_sockopt(cli2->conn, sockops);
9425
9426         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9427
9428         /* Create the file on the Windows connection. */
9429         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9430                           &fnum);
9431         if (!NT_STATUS_IS_OK(status)) {
9432                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9433                 return false;
9434         }
9435
9436         status = cli_close(cli1, fnum);
9437         if (!NT_STATUS_IS_OK(status)) {
9438                 printf("close1 failed (%s)\n", nt_errstr(status));
9439                 return false;
9440         }
9441
9442         cli1->use_oplocks = true;
9443
9444         /* Open with oplock. */
9445         status = cli_ntcreate(cli1,
9446                         fname,
9447                         0,
9448                         FILE_READ_DATA,
9449                         FILE_ATTRIBUTE_NORMAL,
9450                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9451                         FILE_OPEN,
9452                         0,
9453                         0,
9454                         &fnum,
9455                         NULL);
9456
9457         if (!NT_STATUS_IS_OK(status)) {
9458                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9459                 return false;
9460         }
9461
9462         ev = samba_tevent_context_init(talloc_tos());
9463         if (ev == NULL) {
9464                 printf("tevent_context_init failed\n");
9465                 return false;
9466         }
9467
9468         state = talloc_zero(ev, struct posix_acl_oplock_state);
9469         if (state == NULL) {
9470                 printf("talloc failed\n");
9471                 return false;
9472         }
9473         state->ev = ev;
9474         state->cli = cli1;
9475         state->got_break = &got_break;
9476         state->acl_ret = &acl_ret;
9477
9478         oplock_req = cli_smb_oplock_break_waiter_send(
9479                 talloc_tos(), ev, cli1);
9480         if (oplock_req == NULL) {
9481                 printf("cli_smb_oplock_break_waiter_send failed\n");
9482                 return false;
9483         }
9484         tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9485
9486         /* Get ACL on POSIX connection - should break oplock. */
9487         getacl_req = cli_posix_getacl_send(talloc_tos(),
9488                                 ev,
9489                                 cli2,
9490                                 fname);
9491         if (getacl_req == NULL) {
9492                 printf("cli_posix_getacl_send failed\n");
9493                 return false;
9494         }
9495         tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9496
9497         while (!got_break || !acl_ret) {
9498                 int ret;
9499                 ret = tevent_loop_once(ev);
9500                 if (ret == -1) {
9501                         printf("tevent_loop_once failed: %s\n",
9502                                strerror(errno));
9503                         return false;
9504                 }
9505         }
9506
9507         if (!NT_STATUS_IS_OK(state->status)) {
9508                 printf("getacl failed (%s)\n", nt_errstr(state->status));
9509                 correct = false;
9510         }
9511
9512         status = cli_close(cli1, fnum);
9513         if (!NT_STATUS_IS_OK(status)) {
9514                 printf("close2 failed (%s)\n", nt_errstr(status));
9515                 correct = false;
9516         }
9517
9518         status = cli_unlink(cli1,
9519                         fname,
9520                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9521         if (!NT_STATUS_IS_OK(status)) {
9522                 printf("unlink failed (%s)\n", nt_errstr(status));
9523                 correct = false;
9524         }
9525
9526         if (!torture_close_connection(cli1)) {
9527                 correct = false;
9528         }
9529         if (!torture_close_connection(cli2)) {
9530                 correct = false;
9531         }
9532
9533         if (!got_break) {
9534                 correct = false;
9535         }
9536
9537         printf("finished posix acl oplock test\n");
9538
9539         return correct;
9540 }
9541
9542 static bool run_posix_acl_shareroot_test(int dummy)
9543 {
9544         struct cli_state *cli;
9545         NTSTATUS status;
9546         bool correct = false;
9547         char *posix_acl = NULL;
9548         size_t posix_acl_len = 0;
9549         uint16_t num_file_acls = 0;
9550         uint16_t num_dir_acls = 0;
9551         uint16_t i;
9552         uint32_t expected_size = 0;
9553         bool got_user = false;
9554         bool got_group = false;
9555         bool got_other = false;
9556         TALLOC_CTX *frame = NULL;
9557
9558         frame = talloc_stackframe();
9559
9560         printf("starting posix_acl_shareroot test\n");
9561
9562         if (!torture_open_connection(&cli, 0)) {
9563                 TALLOC_FREE(frame);
9564                 return false;
9565         }
9566
9567         smbXcli_conn_set_sockopt(cli->conn, sockops);
9568
9569         status = torture_setup_unix_extensions(cli);
9570         if (!NT_STATUS_IS_OK(status)) {
9571                 printf("Failed to setup unix extensions\n");
9572                 goto out;
9573         }
9574
9575         /* Get the POSIX ACL on the root of the share. */
9576         status = cli_posix_getacl(cli,
9577                                 ".",
9578                                 frame,
9579                                 &posix_acl_len,
9580                                 &posix_acl);
9581
9582         if (!NT_STATUS_IS_OK(status)) {
9583                 printf("cli_posix_getacl of '.' failed (%s)\n",
9584                         nt_errstr(status));
9585                 goto out;
9586         }
9587
9588         if (posix_acl_len < 6 ||
9589                         SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9590                 printf("getfacl ., unknown POSIX acl version %u.\n",
9591                         (unsigned int)CVAL(posix_acl,0) );
9592                 goto out;
9593         }
9594
9595         num_file_acls = SVAL(posix_acl,2);
9596         num_dir_acls = SVAL(posix_acl,4);
9597         expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9598                                 SMB_POSIX_ACL_ENTRY_SIZE*
9599                                 (num_file_acls+num_dir_acls);
9600
9601         if (posix_acl_len != expected_size) {
9602                 printf("incorrect POSIX acl buffer size "
9603                         "(should be %u, was %u).\n",
9604                         (unsigned int)expected_size,
9605                         (unsigned int)posix_acl_len);
9606                 goto out;
9607         }
9608
9609         /*
9610          * We don't need to know what the ACL's are
9611          * we just need to know we have at least 3
9612          * file entries (u,g,o).
9613          */
9614
9615         for (i = 0; i < num_file_acls; i++) {
9616                 unsigned char tagtype =
9617                         CVAL(posix_acl,
9618                                 SMB_POSIX_ACL_HEADER_SIZE+
9619                                 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9620
9621                 switch(tagtype) {
9622                         case SMB_POSIX_ACL_USER_OBJ:
9623                                 got_user = true;
9624                                 break;
9625                         case SMB_POSIX_ACL_GROUP_OBJ:
9626                                 got_group = true;
9627                                 break;
9628                         case SMB_POSIX_ACL_OTHER:
9629                                 got_other = true;
9630                                 break;
9631                         default:
9632                                 break;
9633                 }
9634         }
9635
9636         if (!got_user) {
9637                 printf("Missing user entry\n");
9638                 goto out;
9639         }
9640
9641         if (!got_group) {
9642                 printf("Missing group entry\n");
9643                 goto out;
9644         }
9645
9646         if (!got_other) {
9647                 printf("Missing other entry\n");
9648                 goto out;
9649         }
9650
9651         correct = true;
9652
9653   out:
9654
9655         if (!torture_close_connection(cli)) {
9656                 correct = false;
9657         }
9658
9659         printf("finished posix acl shareroot test\n");
9660         TALLOC_FREE(frame);
9661
9662         return correct;
9663 }
9664
9665 static uint32_t open_attrs_table[] = {
9666                 FILE_ATTRIBUTE_NORMAL,
9667                 FILE_ATTRIBUTE_ARCHIVE,
9668                 FILE_ATTRIBUTE_READONLY,
9669                 FILE_ATTRIBUTE_HIDDEN,
9670                 FILE_ATTRIBUTE_SYSTEM,
9671
9672                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9673                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9674                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9675                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9676                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9677                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9678
9679                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9680                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9681                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9682                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9683 };
9684
9685 struct trunc_open_results {
9686         unsigned int num;
9687         uint32_t init_attr;
9688         uint32_t trunc_attr;
9689         uint32_t result_attr;
9690 };
9691
9692 static struct trunc_open_results attr_results[] = {
9693         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9694         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9695         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9696         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9697         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9698         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9699         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9700         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9701         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9702         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9703         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9704         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9705         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9706         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9707         { 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 },
9708         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9709         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9710         { 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 },
9711         { 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 },
9712         { 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 },
9713         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9714         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9715         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9716         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9717         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9718         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9719 };
9720
9721 static bool run_openattrtest(int dummy)
9722 {
9723         static struct cli_state *cli1;
9724         const char *fname = "\\openattr.file";
9725         uint16_t fnum1;
9726         bool correct = True;
9727         uint32_t attr;
9728         unsigned int i, j, k, l;
9729         NTSTATUS status;
9730
9731         printf("starting open attr test\n");
9732
9733         if (!torture_open_connection(&cli1, 0)) {
9734                 return False;
9735         }
9736
9737         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9738
9739         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9740                 cli_setatr(cli1, fname, 0, 0);
9741                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9742
9743                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9744                                        open_attrs_table[i], FILE_SHARE_NONE,
9745                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9746                 if (!NT_STATUS_IS_OK(status)) {
9747                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9748                         return False;
9749                 }
9750
9751                 status = cli_close(cli1, fnum1);
9752                 if (!NT_STATUS_IS_OK(status)) {
9753                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9754                         return False;
9755                 }
9756
9757                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9758                         status = cli_ntcreate(cli1, fname, 0,
9759                                               FILE_READ_DATA|FILE_WRITE_DATA,
9760                                               open_attrs_table[j],
9761                                               FILE_SHARE_NONE, FILE_OVERWRITE,
9762                                               0, 0, &fnum1, NULL);
9763                         if (!NT_STATUS_IS_OK(status)) {
9764                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9765                                         if (attr_results[l].num == k) {
9766                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9767                                                                 k, open_attrs_table[i],
9768                                                                 open_attrs_table[j],
9769                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
9770                                                 correct = False;
9771                                         }
9772                                 }
9773
9774                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9775                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9776                                                         k, open_attrs_table[i], open_attrs_table[j],
9777                                                         nt_errstr(status));
9778                                         correct = False;
9779                                 }
9780 #if 0
9781                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9782 #endif
9783                                 k++;
9784                                 continue;
9785                         }
9786
9787                         status = cli_close(cli1, fnum1);
9788                         if (!NT_STATUS_IS_OK(status)) {
9789                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9790                                 return False;
9791                         }
9792
9793                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9794                         if (!NT_STATUS_IS_OK(status)) {
9795                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9796                                 return False;
9797                         }
9798
9799 #if 0
9800                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9801                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
9802 #endif
9803
9804                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9805                                 if (attr_results[l].num == k) {
9806                                         if (attr != attr_results[l].result_attr ||
9807                                                         open_attrs_table[i] != attr_results[l].init_attr ||
9808                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
9809                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9810                                                 open_attrs_table[i],
9811                                                 open_attrs_table[j],
9812                                                 (unsigned int)attr,
9813                                                 attr_results[l].result_attr);
9814                                                 correct = False;
9815                                         }
9816                                         break;
9817                                 }
9818                         }
9819                         k++;
9820                 }
9821         }
9822
9823         cli_setatr(cli1, fname, 0, 0);
9824         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9825
9826         printf("open attr test %s.\n", correct ? "passed" : "failed");
9827
9828         if (!torture_close_connection(cli1)) {
9829                 correct = False;
9830         }
9831         return correct;
9832 }
9833
9834 static NTSTATUS list_fn(struct file_info *finfo,
9835                     const char *name, void *state)
9836 {
9837         int *matched = (int *)state;
9838         if (matched != NULL) {
9839                 *matched += 1;
9840         }
9841         return NT_STATUS_OK;
9842 }
9843
9844 /*
9845   test directory listing speed
9846  */
9847 static bool run_dirtest(int dummy)
9848 {
9849         int i;
9850         static struct cli_state *cli;
9851         uint16_t fnum;
9852         struct timeval core_start;
9853         bool correct = True;
9854         int matched;
9855
9856         printf("starting directory test\n");
9857
9858         if (!torture_open_connection(&cli, 0)) {
9859                 return False;
9860         }
9861
9862         smbXcli_conn_set_sockopt(cli->conn, sockops);
9863
9864         srandom(0);
9865         for (i=0;i<torture_numops;i++) {
9866                 fstring fname;
9867                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9868                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9869                         fprintf(stderr,"Failed to open %s\n", fname);
9870                         return False;
9871                 }
9872                 cli_close(cli, fnum);
9873         }
9874
9875         core_start = timeval_current();
9876
9877         matched = 0;
9878         cli_list(cli, "a*.*", 0, list_fn, &matched);
9879         printf("Matched %d\n", matched);
9880
9881         matched = 0;
9882         cli_list(cli, "b*.*", 0, list_fn, &matched);
9883         printf("Matched %d\n", matched);
9884
9885         matched = 0;
9886         cli_list(cli, "xyzabc", 0, list_fn, &matched);
9887         printf("Matched %d\n", matched);
9888
9889         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9890
9891         srandom(0);
9892         for (i=0;i<torture_numops;i++) {
9893                 fstring fname;
9894                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9895                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9896         }
9897
9898         if (!torture_close_connection(cli)) {
9899                 correct = False;
9900         }
9901
9902         printf("finished dirtest\n");
9903
9904         return correct;
9905 }
9906
9907 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9908                    void *state)
9909 {
9910         struct cli_state *pcli = (struct cli_state *)state;
9911         fstring fname;
9912         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9913
9914         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9915                 return NT_STATUS_OK;
9916
9917         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9918                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9919                         printf("del_fn: failed to rmdir %s\n,", fname );
9920         } else {
9921                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9922                         printf("del_fn: failed to unlink %s\n,", fname );
9923         }
9924         return NT_STATUS_OK;
9925 }
9926
9927
9928 /*
9929    send a raw ioctl - used by the torture code
9930 */
9931 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9932                               uint16_t fnum,
9933                               uint32_t code,
9934                               DATA_BLOB *blob)
9935 {
9936         uint16_t vwv[3];
9937         NTSTATUS status;
9938
9939         PUSH_LE_U16(vwv + 0, 0, fnum);
9940         PUSH_LE_U16(vwv + 1, 0, code >> 16);
9941         PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9942
9943         status = cli_smb(talloc_tos(),
9944                          cli,
9945                          SMBioctl,
9946                          0,
9947                          3,
9948                          vwv,
9949                          0,
9950                          NULL,
9951                          NULL,
9952                          0,
9953                          NULL,
9954                          NULL,
9955                          NULL,
9956                          NULL);
9957         if (!NT_STATUS_IS_OK(status)) {
9958                 return status;
9959         }
9960         *blob = data_blob_null;
9961         return NT_STATUS_OK;
9962 }
9963
9964 /*
9965   sees what IOCTLs are supported
9966  */
9967 bool torture_ioctl_test(int dummy)
9968 {
9969         static struct cli_state *cli;
9970         uint16_t device, function;
9971         uint16_t fnum;
9972         const char *fname = "\\ioctl.dat";
9973         DATA_BLOB blob;
9974         NTSTATUS status;
9975
9976         if (!torture_open_connection(&cli, 0)) {
9977                 return False;
9978         }
9979
9980         printf("starting ioctl test\n");
9981
9982         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9983
9984         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9985         if (!NT_STATUS_IS_OK(status)) {
9986                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9987                 return False;
9988         }
9989
9990         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9991         printf("ioctl device info: %s\n", nt_errstr(status));
9992
9993         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9994         printf("ioctl job info: %s\n", nt_errstr(status));
9995
9996         for (device=0;device<0x100;device++) {
9997                 printf("ioctl test with device = 0x%x\n", device);
9998                 for (function=0;function<0x100;function++) {
9999                         uint32_t code = (device<<16) | function;
10000
10001                         status = cli_raw_ioctl(cli, fnum, code, &blob);
10002
10003                         if (NT_STATUS_IS_OK(status)) {
10004                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10005                                        (int)blob.length);
10006                                 data_blob_free(&blob);
10007                         }
10008                 }
10009         }
10010
10011         if (!torture_close_connection(cli)) {
10012                 return False;
10013         }
10014
10015         return True;
10016 }
10017
10018
10019 /*
10020   tries variants of chkpath
10021  */
10022 bool torture_chkpath_test(int dummy)
10023 {
10024         static struct cli_state *cli;
10025         uint16_t fnum;
10026         bool ret;
10027         NTSTATUS status;
10028
10029         if (!torture_open_connection(&cli, 0)) {
10030                 return False;
10031         }
10032
10033         printf("starting chkpath test\n");
10034
10035         /* cleanup from an old run */
10036         torture_deltree(cli, "\\chkpath.dir");
10037
10038         status = cli_mkdir(cli, "\\chkpath.dir");
10039         if (!NT_STATUS_IS_OK(status)) {
10040                 printf("mkdir1 failed : %s\n", nt_errstr(status));
10041                 return False;
10042         }
10043
10044         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10045         if (!NT_STATUS_IS_OK(status)) {
10046                 printf("mkdir2 failed : %s\n", nt_errstr(status));
10047                 return False;
10048         }
10049
10050         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10051                           DENY_NONE, &fnum);
10052         if (!NT_STATUS_IS_OK(status)) {
10053                 printf("open1 failed (%s)\n", nt_errstr(status));
10054                 return False;
10055         }
10056         cli_close(cli, fnum);
10057
10058         status = cli_chkpath(cli, "\\chkpath.dir");
10059         if (!NT_STATUS_IS_OK(status)) {
10060                 printf("chkpath1 failed: %s\n", nt_errstr(status));
10061                 ret = False;
10062         }
10063
10064         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10065         if (!NT_STATUS_IS_OK(status)) {
10066                 printf("chkpath2 failed: %s\n", nt_errstr(status));
10067                 ret = False;
10068         }
10069
10070         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10071         if (!NT_STATUS_IS_OK(status)) {
10072                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10073                                   NT_STATUS_NOT_A_DIRECTORY);
10074         } else {
10075                 printf("* chkpath on a file should fail\n");
10076                 ret = False;
10077         }
10078
10079         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10080         if (!NT_STATUS_IS_OK(status)) {
10081                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10082                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
10083         } else {
10084                 printf("* chkpath on a non existent file should fail\n");
10085                 ret = False;
10086         }
10087
10088         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10089         if (!NT_STATUS_IS_OK(status)) {
10090                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10091                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
10092         } else {
10093                 printf("* chkpath on a non existent component should fail\n");
10094                 ret = False;
10095         }
10096
10097         torture_deltree(cli, "\\chkpath.dir");
10098
10099         if (!torture_close_connection(cli)) {
10100                 return False;
10101         }
10102
10103         return ret;
10104 }
10105
10106 static bool run_eatest(int dummy)
10107 {
10108         static struct cli_state *cli;
10109         const char *fname = "\\eatest.txt";
10110         bool correct = True;
10111         uint16_t fnum;
10112         size_t i, num_eas;
10113         struct ea_struct *ea_list = NULL;
10114         TALLOC_CTX *mem_ctx = talloc_init("eatest");
10115         NTSTATUS status;
10116
10117         printf("starting eatest\n");
10118
10119         if (!torture_open_connection(&cli, 0)) {
10120                 talloc_destroy(mem_ctx);
10121                 return False;
10122         }
10123
10124         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10125
10126         status = cli_ntcreate(cli, fname, 0,
10127                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10128                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10129                               0x4044, 0, &fnum, NULL);
10130         if (!NT_STATUS_IS_OK(status)) {
10131                 printf("open failed - %s\n", nt_errstr(status));
10132                 talloc_destroy(mem_ctx);
10133                 return False;
10134         }
10135
10136         for (i = 0; i < 10; i++) {
10137                 fstring ea_name, ea_val;
10138
10139                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10140                 memset(ea_val, (char)i+1, i+1);
10141                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10142                 if (!NT_STATUS_IS_OK(status)) {
10143                         printf("ea_set of name %s failed - %s\n", ea_name,
10144                                nt_errstr(status));
10145                         talloc_destroy(mem_ctx);
10146                         return False;
10147                 }
10148         }
10149
10150         cli_close(cli, fnum);
10151         for (i = 0; i < 10; i++) {
10152                 fstring ea_name, ea_val;
10153
10154                 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10155                 memset(ea_val, (char)i+1, i+1);
10156                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10157                 if (!NT_STATUS_IS_OK(status)) {
10158                         printf("ea_set of name %s failed - %s\n", ea_name,
10159                                nt_errstr(status));
10160                         talloc_destroy(mem_ctx);
10161                         return False;
10162                 }
10163         }
10164
10165         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10166         if (!NT_STATUS_IS_OK(status)) {
10167                 printf("ea_get list failed - %s\n", nt_errstr(status));
10168                 correct = False;
10169         }
10170
10171         printf("num_eas = %d\n", (int)num_eas);
10172
10173         if (num_eas != 20) {
10174                 printf("Should be 20 EA's stored... failing.\n");
10175                 correct = False;
10176         }
10177
10178         for (i = 0; i < num_eas; i++) {
10179                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10180                 dump_data(0, ea_list[i].value.data,
10181                           ea_list[i].value.length);
10182         }
10183
10184         /* Setting EA's to zero length deletes them. Test this */
10185         printf("Now deleting all EA's - case independent....\n");
10186
10187 #if 1
10188         cli_set_ea_path(cli, fname, "", "", 0);
10189 #else
10190         for (i = 0; i < 20; i++) {
10191                 fstring ea_name;
10192                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10193                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10194                 if (!NT_STATUS_IS_OK(status)) {
10195                         printf("ea_set of name %s failed - %s\n", ea_name,
10196                                nt_errstr(status));
10197                         talloc_destroy(mem_ctx);
10198                         return False;
10199                 }
10200         }
10201 #endif
10202
10203         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10204         if (!NT_STATUS_IS_OK(status)) {
10205                 printf("ea_get list failed - %s\n", nt_errstr(status));
10206                 correct = False;
10207         }
10208
10209         printf("num_eas = %d\n", (int)num_eas);
10210         for (i = 0; i < num_eas; i++) {
10211                 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10212                 dump_data(0, ea_list[i].value.data,
10213                           ea_list[i].value.length);
10214         }
10215
10216         if (num_eas != 0) {
10217                 printf("deleting EA's failed.\n");
10218                 correct = False;
10219         }
10220
10221         /* Try and delete a non existent EA. */
10222         status = cli_set_ea_path(cli, fname, "foo", "", 0);
10223         if (!NT_STATUS_IS_OK(status)) {
10224                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10225                        nt_errstr(status));
10226                 correct = False;
10227         }
10228
10229         talloc_destroy(mem_ctx);
10230         if (!torture_close_connection(cli)) {
10231                 correct = False;
10232         }
10233
10234         return correct;
10235 }
10236
10237 static bool run_dirtest1(int dummy)
10238 {
10239         int i;
10240         static struct cli_state *cli;
10241         uint16_t fnum;
10242         int num_seen;
10243         bool correct = True;
10244
10245         printf("starting directory test\n");
10246
10247         if (!torture_open_connection(&cli, 0)) {
10248                 return False;
10249         }
10250
10251         smbXcli_conn_set_sockopt(cli->conn, sockops);
10252
10253         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10254         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10255         cli_rmdir(cli, "\\LISTDIR");
10256         cli_mkdir(cli, "\\LISTDIR");
10257
10258         /* Create 1000 files and 1000 directories. */
10259         for (i=0;i<1000;i++) {
10260                 fstring fname;
10261                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10262                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10263                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10264                                    0, 0, &fnum, NULL))) {
10265                         fprintf(stderr,"Failed to open %s\n", fname);
10266                         return False;
10267                 }
10268                 cli_close(cli, fnum);
10269         }
10270         for (i=0;i<1000;i++) {
10271                 fstring fname;
10272                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10273                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10274                         fprintf(stderr,"Failed to open %s\n", fname);
10275                         return False;
10276                 }
10277         }
10278
10279         /* Now ensure that doing an old list sees both files and directories. */
10280         num_seen = 0;
10281         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10282         printf("num_seen = %d\n", num_seen );
10283         /* We should see 100 files + 1000 directories + . and .. */
10284         if (num_seen != 2002)
10285                 correct = False;
10286
10287         /* Ensure if we have the "must have" bits we only see the
10288          * relevant entries.
10289          */
10290         num_seen = 0;
10291         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10292         printf("num_seen = %d\n", num_seen );
10293         if (num_seen != 1002)
10294                 correct = False;
10295
10296         num_seen = 0;
10297         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10298         printf("num_seen = %d\n", num_seen );
10299         if (num_seen != 1000)
10300                 correct = False;
10301
10302         /* Delete everything. */
10303         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10304         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10305         cli_rmdir(cli, "\\LISTDIR");
10306
10307 #if 0
10308         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10309         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10310         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10311 #endif
10312
10313         if (!torture_close_connection(cli)) {
10314                 correct = False;
10315         }
10316
10317         printf("finished dirtest1\n");
10318
10319         return correct;
10320 }
10321
10322 static bool run_error_map_extract(int dummy) {
10323
10324         static struct cli_state *c_dos;
10325         static struct cli_state *c_nt;
10326         NTSTATUS status;
10327
10328         uint32_t error;
10329
10330         uint32_t errnum;
10331         uint8_t errclass;
10332
10333         NTSTATUS nt_status;
10334
10335         fstring user;
10336
10337         /* NT-Error connection */
10338
10339         disable_spnego = true;
10340         if (!(c_nt = open_nbt_connection())) {
10341                 disable_spnego = false;
10342                 return False;
10343         }
10344         disable_spnego = false;
10345
10346         status = smbXcli_negprot(c_nt->conn,
10347                                  c_nt->timeout,
10348                                  PROTOCOL_CORE,
10349                                  PROTOCOL_NT1,
10350                                  NULL,
10351                                  NULL,
10352                                  NULL);
10353
10354         if (!NT_STATUS_IS_OK(status)) {
10355                 printf("%s rejected the NT-error negprot (%s)\n", host,
10356                        nt_errstr(status));
10357                 cli_shutdown(c_nt);
10358                 return False;
10359         }
10360
10361         status = cli_session_setup_anon(c_nt);
10362         if (!NT_STATUS_IS_OK(status)) {
10363                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10364                 return False;
10365         }
10366
10367         /* DOS-Error connection */
10368
10369         disable_spnego = true;
10370         force_dos_errors = true;
10371         if (!(c_dos = open_nbt_connection())) {
10372                 disable_spnego = false;
10373                 force_dos_errors = false;
10374                 return False;
10375         }
10376         disable_spnego = false;
10377         force_dos_errors = false;
10378
10379         status = smbXcli_negprot(c_dos->conn,
10380                                  c_dos->timeout,
10381                                  PROTOCOL_CORE,
10382                                  PROTOCOL_NT1,
10383                                  NULL,
10384                                  NULL,
10385                                  NULL);
10386         if (!NT_STATUS_IS_OK(status)) {
10387                 printf("%s rejected the DOS-error negprot (%s)\n", host,
10388                        nt_errstr(status));
10389                 cli_shutdown(c_dos);
10390                 return False;
10391         }
10392
10393         status = cli_session_setup_anon(c_dos);
10394         if (!NT_STATUS_IS_OK(status)) {
10395                 printf("%s rejected the DOS-error initial session setup (%s)\n",
10396                         host, nt_errstr(status));
10397                 return False;
10398         }
10399
10400         c_nt->map_dos_errors = false;
10401         c_dos->map_dos_errors = false;
10402
10403         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10404                 struct cli_credentials *user_creds = NULL;
10405
10406                 fstr_sprintf(user, "%X", error);
10407
10408                 user_creds = cli_session_creds_init(talloc_tos(),
10409                                                     user,
10410                                                     workgroup,
10411                                                     NULL, /* realm */
10412                                                     password,
10413                                                     false, /* use_kerberos */
10414                                                     false, /* fallback_after_kerberos */
10415                                                     false, /* use_ccache */
10416                                                     false); /* password_is_nt_hash */
10417                 if (user_creds == NULL) {
10418                         printf("cli_session_creds_init(%s) failed\n", user);
10419                         return false;
10420                 }
10421
10422                 status = cli_session_setup_creds(c_nt, user_creds);
10423                 if (NT_STATUS_IS_OK(status)) {
10424                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10425                 }
10426
10427                 /* Case #1: 32-bit NT errors */
10428                 if (!NT_STATUS_IS_DOS(status)) {
10429                         nt_status = status;
10430                 } else {
10431                         printf("/** Dos error on NT connection! (%s) */\n", 
10432                                nt_errstr(status));
10433                         nt_status = NT_STATUS(0xc0000000);
10434                 }
10435
10436                 status = cli_session_setup_creds(c_dos, user_creds);
10437                 if (NT_STATUS_IS_OK(status)) {
10438                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
10439                 }
10440
10441                 /* Case #1: 32-bit NT errors */
10442                 if (NT_STATUS_IS_DOS(status)) {
10443                         printf("/** NT error on DOS connection! (%s) */\n", 
10444                                nt_errstr(status));
10445                         errnum = errclass = 0;
10446                 } else {
10447                         errclass = NT_STATUS_DOS_CLASS(status);
10448                         errnum = NT_STATUS_DOS_CODE(status);
10449                 }
10450
10451                 if (NT_STATUS_V(nt_status) != error) { 
10452                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
10453                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
10454                                get_nt_error_c_code(talloc_tos(), nt_status));
10455                 }
10456
10457                 printf("\t{%s,\t%s,\t%s},\n", 
10458                        smb_dos_err_class(errclass), 
10459                        smb_dos_err_name(errclass, errnum), 
10460                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10461
10462                 TALLOC_FREE(user_creds);
10463         }
10464         return True;
10465 }
10466
10467 static bool run_sesssetup_bench(int dummy)
10468 {
10469         static struct cli_state *c;
10470         const char *fname = "\\file.dat";
10471         uint16_t fnum;
10472         NTSTATUS status;
10473         int i;
10474
10475         if (!torture_open_connection(&c, 0)) {
10476                 return false;
10477         }
10478
10479         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10480                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10481                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10482         if (!NT_STATUS_IS_OK(status)) {
10483                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10484                 return false;
10485         }
10486
10487         for (i=0; i<torture_numops; i++) {
10488                 status = cli_session_setup_creds(c, torture_creds);
10489                 if (!NT_STATUS_IS_OK(status)) {
10490                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
10491                                  __location__, nt_errstr(status));
10492                         return false;
10493                 }
10494
10495                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
10496
10497                 status = cli_ulogoff(c);
10498                 if (!NT_STATUS_IS_OK(status)) {
10499                         d_printf("(%s) cli_ulogoff failed: %s\n",
10500                                  __location__, nt_errstr(status));
10501                         return false;
10502                 }
10503         }
10504
10505         return true;
10506 }
10507
10508 static bool subst_test(const char *str, const char *user, const char *domain,
10509                        uid_t uid, gid_t gid, const char *expected)
10510 {
10511         char *subst;
10512         bool result = true;
10513
10514         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10515
10516         if (strcmp(subst, expected) != 0) {
10517                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10518                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10519                        expected);
10520                 result = false;
10521         }
10522
10523         TALLOC_FREE(subst);
10524         return result;
10525 }
10526
10527 static void chain1_open_completion(struct tevent_req *req)
10528 {
10529         uint16_t fnum;
10530         NTSTATUS status;
10531         status = cli_openx_recv(req, &fnum);
10532         TALLOC_FREE(req);
10533
10534         d_printf("cli_openx_recv returned %s: %d\n",
10535                  nt_errstr(status),
10536                  NT_STATUS_IS_OK(status) ? fnum : -1);
10537 }
10538
10539 static void chain1_write_completion(struct tevent_req *req)
10540 {
10541         size_t written;
10542         NTSTATUS status;
10543         status = cli_write_andx_recv(req, &written);
10544         TALLOC_FREE(req);
10545
10546         d_printf("cli_write_andx_recv returned %s: %d\n",
10547                  nt_errstr(status),
10548                  NT_STATUS_IS_OK(status) ? (int)written : -1);
10549 }
10550
10551 static void chain1_close_completion(struct tevent_req *req)
10552 {
10553         NTSTATUS status;
10554         bool *done = (bool *)tevent_req_callback_data_void(req);
10555
10556         status = cli_close_recv(req);
10557         *done = true;
10558
10559         TALLOC_FREE(req);
10560
10561         d_printf("cli_close returned %s\n", nt_errstr(status));
10562 }
10563
10564 static bool run_chain1(int dummy)
10565 {
10566         struct cli_state *cli1;
10567         struct tevent_context *evt = samba_tevent_context_init(NULL);
10568         struct tevent_req *reqs[3], *smbreqs[3];
10569         bool done = false;
10570         const char *str = "foobar";
10571         const char *fname = "\\test_chain";
10572         NTSTATUS status;
10573
10574         printf("starting chain1 test\n");
10575         if (!torture_open_connection(&cli1, 0)) {
10576                 return False;
10577         }
10578
10579         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10580
10581         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10582
10583         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10584                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
10585         if (reqs[0] == NULL) return false;
10586         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10587
10588
10589         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10590                                         (const uint8_t *)str, 0, strlen(str)+1,
10591                                         smbreqs, 1, &smbreqs[1]);
10592         if (reqs[1] == NULL) return false;
10593         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10594
10595         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10596         if (reqs[2] == NULL) return false;
10597         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10598
10599         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10600         if (!NT_STATUS_IS_OK(status)) {
10601                 return false;
10602         }
10603
10604         while (!done) {
10605                 tevent_loop_once(evt);
10606         }
10607
10608         torture_close_connection(cli1);
10609         return True;
10610 }
10611
10612 static void chain2_sesssetup_completion(struct tevent_req *req)
10613 {
10614         NTSTATUS status;
10615         status = cli_session_setup_guest_recv(req);
10616         d_printf("sesssetup returned %s\n", nt_errstr(status));
10617 }
10618
10619 static void chain2_tcon_completion(struct tevent_req *req)
10620 {
10621         bool *done = (bool *)tevent_req_callback_data_void(req);
10622         NTSTATUS status;
10623         status = cli_tcon_andx_recv(req);
10624         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10625         *done = true;
10626 }
10627
10628 static bool run_chain2(int dummy)
10629 {
10630         struct cli_state *cli1;
10631         struct tevent_context *evt = samba_tevent_context_init(NULL);
10632         struct tevent_req *reqs[2], *smbreqs[2];
10633         bool done = false;
10634         NTSTATUS status;
10635         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10636
10637         printf("starting chain2 test\n");
10638         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10639                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
10640         if (!NT_STATUS_IS_OK(status)) {
10641                 return False;
10642         }
10643
10644         smbXcli_conn_set_sockopt(cli1->conn, sockops);
10645
10646         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10647                                                  &smbreqs[0]);
10648         if (reqs[0] == NULL) return false;
10649         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10650
10651         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10652                                        "?????", NULL, 0, &smbreqs[1]);
10653         if (reqs[1] == NULL) return false;
10654         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10655
10656         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10657         if (!NT_STATUS_IS_OK(status)) {
10658                 return false;
10659         }
10660
10661         while (!done) {
10662                 tevent_loop_once(evt);
10663         }
10664
10665         torture_close_connection(cli1);
10666         return True;
10667 }
10668
10669
10670 struct torture_createdel_state {
10671         struct tevent_context *ev;
10672         struct cli_state *cli;
10673 };
10674
10675 static void torture_createdel_created(struct tevent_req *subreq);
10676 static void torture_createdel_closed(struct tevent_req *subreq);
10677
10678 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10679                                                  struct tevent_context *ev,
10680                                                  struct cli_state *cli,
10681                                                  const char *name)
10682 {
10683         struct tevent_req *req, *subreq;
10684         struct torture_createdel_state *state;
10685
10686         req = tevent_req_create(mem_ctx, &state,
10687                                 struct torture_createdel_state);
10688         if (req == NULL) {
10689                 return NULL;
10690         }
10691         state->ev = ev;
10692         state->cli = cli;
10693
10694         subreq = cli_ntcreate_send(
10695                 state, ev, cli, name, 0,
10696                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10697                 FILE_ATTRIBUTE_NORMAL,
10698                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10699                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10700                 SMB2_IMPERSONATION_IMPERSONATION, 0);
10701
10702         if (tevent_req_nomem(subreq, req)) {
10703                 return tevent_req_post(req, ev);
10704         }
10705         tevent_req_set_callback(subreq, torture_createdel_created, req);
10706         return req;
10707 }
10708
10709 static void torture_createdel_created(struct tevent_req *subreq)
10710 {
10711         struct tevent_req *req = tevent_req_callback_data(
10712                 subreq, struct tevent_req);
10713         struct torture_createdel_state *state = tevent_req_data(
10714                 req, struct torture_createdel_state);
10715         NTSTATUS status;
10716         uint16_t fnum;
10717
10718         status = cli_ntcreate_recv(subreq, &fnum, NULL);
10719         TALLOC_FREE(subreq);
10720         if (tevent_req_nterror(req, status)) {
10721                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10722                            nt_errstr(status)));
10723                 return;
10724         }
10725
10726         subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10727         if (tevent_req_nomem(subreq, req)) {
10728                 return;
10729         }
10730         tevent_req_set_callback(subreq, torture_createdel_closed, req);
10731 }
10732
10733 static void torture_createdel_closed(struct tevent_req *subreq)
10734 {
10735         struct tevent_req *req = tevent_req_callback_data(
10736                 subreq, struct tevent_req);
10737         NTSTATUS status;
10738
10739         status = cli_close_recv(subreq);
10740         if (tevent_req_nterror(req, status)) {
10741                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10742                 return;
10743         }
10744         tevent_req_done(req);
10745 }
10746
10747 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10748 {
10749         return tevent_req_simple_recv_ntstatus(req);
10750 }
10751
10752 struct torture_createdels_state {
10753         struct tevent_context *ev;
10754         struct cli_state *cli;
10755         const char *base_name;
10756         int sent;
10757         int received;
10758         int num_files;
10759         struct tevent_req **reqs;
10760 };
10761
10762 static void torture_createdels_done(struct tevent_req *subreq);
10763
10764 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10765                                                   struct tevent_context *ev,
10766                                                   struct cli_state *cli,
10767                                                   const char *base_name,
10768                                                   int num_parallel,
10769                                                   int num_files)
10770 {
10771         struct tevent_req *req;
10772         struct torture_createdels_state *state;
10773         int i;
10774
10775         req = tevent_req_create(mem_ctx, &state,
10776                                 struct torture_createdels_state);
10777         if (req == NULL) {
10778                 return NULL;
10779         }
10780         state->ev = ev;
10781         state->cli = cli;
10782         state->base_name = talloc_strdup(state, base_name);
10783         if (tevent_req_nomem(state->base_name, req)) {
10784                 return tevent_req_post(req, ev);
10785         }
10786         state->num_files = MAX(num_parallel, num_files);
10787         state->sent = 0;
10788         state->received = 0;
10789
10790         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10791         if (tevent_req_nomem(state->reqs, req)) {
10792                 return tevent_req_post(req, ev);
10793         }
10794
10795         for (i=0; i<num_parallel; i++) {
10796                 char *name;
10797
10798                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10799                                        state->sent);
10800                 if (tevent_req_nomem(name, req)) {
10801                         return tevent_req_post(req, ev);
10802                 }
10803                 state->reqs[i] = torture_createdel_send(
10804                         state->reqs, state->ev, state->cli, name);
10805                 if (tevent_req_nomem(state->reqs[i], req)) {
10806                         return tevent_req_post(req, ev);
10807                 }
10808                 name = talloc_move(state->reqs[i], &name);
10809                 tevent_req_set_callback(state->reqs[i],
10810                                         torture_createdels_done, req);
10811                 state->sent += 1;
10812         }
10813         return req;
10814 }
10815
10816 static void torture_createdels_done(struct tevent_req *subreq)
10817 {
10818         struct tevent_req *req = tevent_req_callback_data(
10819                 subreq, struct tevent_req);
10820         struct torture_createdels_state *state = tevent_req_data(
10821                 req, struct torture_createdels_state);
10822         size_t i, num_parallel = talloc_array_length(state->reqs);
10823         NTSTATUS status;
10824         char *name;
10825
10826         status = torture_createdel_recv(subreq);
10827         if (!NT_STATUS_IS_OK(status)){
10828                 DEBUG(10, ("torture_createdel_recv returned %s\n",
10829                            nt_errstr(status)));
10830                 TALLOC_FREE(subreq);
10831                 tevent_req_nterror(req, status);
10832                 return;
10833         }
10834
10835         for (i=0; i<num_parallel; i++) {
10836                 if (subreq == state->reqs[i]) {
10837                         break;
10838                 }
10839         }
10840         if (i == num_parallel) {
10841                 DEBUG(10, ("received something we did not send\n"));
10842                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10843                 return;
10844         }
10845         TALLOC_FREE(state->reqs[i]);
10846
10847         if (state->sent >= state->num_files) {
10848                 tevent_req_done(req);
10849                 return;
10850         }
10851
10852         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10853                                state->sent);
10854         if (tevent_req_nomem(name, req)) {
10855                 return;
10856         }
10857         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10858                                                 state->cli, name);
10859         if (tevent_req_nomem(state->reqs[i], req)) {
10860                 return;
10861         }
10862         name = talloc_move(state->reqs[i], &name);
10863         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10864         state->sent += 1;
10865 }
10866
10867 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10868 {
10869         return tevent_req_simple_recv_ntstatus(req);
10870 }
10871
10872 struct swallow_notify_state {
10873         struct tevent_context *ev;
10874         struct cli_state *cli;
10875         uint16_t fnum;
10876         uint32_t completion_filter;
10877         bool recursive;
10878         bool (*fn)(uint32_t action, const char *name, void *priv);
10879         void *priv;
10880 };
10881
10882 static void swallow_notify_done(struct tevent_req *subreq);
10883
10884 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10885                                               struct tevent_context *ev,
10886                                               struct cli_state *cli,
10887                                               uint16_t fnum,
10888                                               uint32_t completion_filter,
10889                                               bool recursive,
10890                                               bool (*fn)(uint32_t action,
10891                                                          const char *name,
10892                                                          void *priv),
10893                                               void *priv)
10894 {
10895         struct tevent_req *req, *subreq;
10896         struct swallow_notify_state *state;
10897
10898         req = tevent_req_create(mem_ctx, &state,
10899                                 struct swallow_notify_state);
10900         if (req == NULL) {
10901                 return NULL;
10902         }
10903         state->ev = ev;
10904         state->cli = cli;
10905         state->fnum = fnum;
10906         state->completion_filter = completion_filter;
10907         state->recursive = recursive;
10908         state->fn = fn;
10909         state->priv = priv;
10910
10911         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10912                                  0xffff, state->completion_filter,
10913                                  state->recursive);
10914         if (tevent_req_nomem(subreq, req)) {
10915                 return tevent_req_post(req, ev);
10916         }
10917         tevent_req_set_callback(subreq, swallow_notify_done, req);
10918         return req;
10919 }
10920
10921 static void swallow_notify_done(struct tevent_req *subreq)
10922 {
10923         struct tevent_req *req = tevent_req_callback_data(
10924                 subreq, struct tevent_req);
10925         struct swallow_notify_state *state = tevent_req_data(
10926                 req, struct swallow_notify_state);
10927         NTSTATUS status;
10928         uint32_t i, num_changes;
10929         struct notify_change *changes;
10930
10931         status = cli_notify_recv(subreq, state, &num_changes, &changes);
10932         TALLOC_FREE(subreq);
10933         if (!NT_STATUS_IS_OK(status)) {
10934                 DEBUG(10, ("cli_notify_recv returned %s\n",
10935                            nt_errstr(status)));
10936                 tevent_req_nterror(req, status);
10937                 return;
10938         }
10939
10940         for (i=0; i<num_changes; i++) {
10941                 state->fn(changes[i].action, changes[i].name, state->priv);
10942         }
10943         TALLOC_FREE(changes);
10944
10945         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10946                                  0xffff, state->completion_filter,
10947                                  state->recursive);
10948         if (tevent_req_nomem(subreq, req)) {
10949                 return;
10950         }
10951         tevent_req_set_callback(subreq, swallow_notify_done, req);
10952 }
10953
10954 static bool print_notifies(uint32_t action, const char *name, void *priv)
10955 {
10956         if (DEBUGLEVEL > 5) {
10957                 d_printf("%d %s\n", (int)action, name);
10958         }
10959         return true;
10960 }
10961
10962 static void notify_bench_done(struct tevent_req *req)
10963 {
10964         int *num_finished = (int *)tevent_req_callback_data_void(req);
10965         *num_finished += 1;
10966 }
10967
10968 static bool run_notify_bench(int dummy)
10969 {
10970         const char *dname = "\\notify-bench";
10971         struct tevent_context *ev;
10972         NTSTATUS status;
10973         uint16_t dnum;
10974         struct tevent_req *req1;
10975         struct tevent_req *req2 = NULL;
10976         int i, num_unc_names;
10977         int num_finished = 0;
10978
10979         printf("starting notify-bench test\n");
10980
10981         if (use_multishare_conn) {
10982                 char **unc_list;
10983                 unc_list = file_lines_load(multishare_conn_fname,
10984                                            &num_unc_names, 0, NULL);
10985                 if (!unc_list || num_unc_names <= 0) {
10986                         d_printf("Failed to load unc names list from '%s'\n",
10987                                  multishare_conn_fname);
10988                         return false;
10989                 }
10990                 TALLOC_FREE(unc_list);
10991         } else {
10992                 num_unc_names = 1;
10993         }
10994
10995         ev = samba_tevent_context_init(talloc_tos());
10996         if (ev == NULL) {
10997                 d_printf("tevent_context_init failed\n");
10998                 return false;
10999         }
11000
11001         for (i=0; i<num_unc_names; i++) {
11002                 struct cli_state *cli;
11003                 char *base_fname;
11004
11005                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11006                                              dname, i);
11007                 if (base_fname == NULL) {
11008                         return false;
11009                 }
11010
11011                 if (!torture_open_connection(&cli, i)) {
11012                         return false;
11013                 }
11014
11015                 status = cli_ntcreate(cli, dname, 0,
11016                                       MAXIMUM_ALLOWED_ACCESS,
11017                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11018                                       FILE_SHARE_DELETE,
11019                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11020                                       &dnum, NULL);
11021
11022                 if (!NT_STATUS_IS_OK(status)) {
11023                         d_printf("Could not create %s: %s\n", dname,
11024                                  nt_errstr(status));
11025                         return false;
11026                 }
11027
11028                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11029                                            FILE_NOTIFY_CHANGE_FILE_NAME |
11030                                            FILE_NOTIFY_CHANGE_DIR_NAME |
11031                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
11032                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
11033                                            false, print_notifies, NULL);
11034                 if (req1 == NULL) {
11035                         d_printf("Could not create notify request\n");
11036                         return false;
11037                 }
11038
11039                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11040                                                base_fname, 10, torture_numops);
11041                 if (req2 == NULL) {
11042                         d_printf("Could not create createdels request\n");
11043                         return false;
11044                 }
11045                 TALLOC_FREE(base_fname);
11046
11047                 tevent_req_set_callback(req2, notify_bench_done,
11048                                         &num_finished);
11049         }
11050
11051         while (num_finished < num_unc_names) {
11052                 int ret;
11053                 ret = tevent_loop_once(ev);
11054                 if (ret != 0) {
11055                         d_printf("tevent_loop_once failed\n");
11056                         return false;
11057                 }
11058         }
11059
11060         if (!tevent_req_poll(req2, ev)) {
11061                 d_printf("tevent_req_poll failed\n");
11062         }
11063
11064         status = torture_createdels_recv(req2);
11065         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11066
11067         return true;
11068 }
11069
11070 static bool run_mangle1(int dummy)
11071 {
11072         struct cli_state *cli;
11073         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11074         uint16_t fnum;
11075         fstring alt_name;
11076         NTSTATUS status;
11077
11078         printf("starting mangle1 test\n");
11079         if (!torture_open_connection(&cli, 0)) {
11080                 return False;
11081         }
11082
11083         smbXcli_conn_set_sockopt(cli->conn, sockops);
11084
11085         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11086                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11087                               0, 0, &fnum, NULL);
11088         if (!NT_STATUS_IS_OK(status)) {
11089                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11090                 return false;
11091         }
11092         cli_close(cli, fnum);
11093
11094         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11095         if (!NT_STATUS_IS_OK(status)) {
11096                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11097                          nt_errstr(status));
11098                 return false;
11099         }
11100         d_printf("alt_name: %s\n", alt_name);
11101
11102         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11103         if (!NT_STATUS_IS_OK(status)) {
11104                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11105                          nt_errstr(status));
11106                 return false;
11107         }
11108         cli_close(cli, fnum);
11109
11110         status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11111         if (!NT_STATUS_IS_OK(status)) {
11112                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11113                          nt_errstr(status));
11114                 return false;
11115         }
11116
11117         return true;
11118 }
11119
11120 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11121                                                  const char *mask,
11122                                                  void *state)
11123 {
11124         if (f->short_name == NULL) {
11125                 return NT_STATUS_OK;
11126         }
11127
11128         if (strlen(f->short_name) == 0) {
11129                 return NT_STATUS_OK;
11130         }
11131
11132         printf("unexpected shortname: %s\n", f->short_name);
11133
11134         return NT_STATUS_OBJECT_NAME_INVALID;
11135 }
11136
11137 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11138                                             const char *mask,
11139                                             void *state)
11140 {
11141         char *name = state;
11142
11143         printf("name: %s\n", f->name);
11144         fstrcpy(name, f->name);
11145         return NT_STATUS_OK;
11146 }
11147
11148 static bool run_mangle_illegal(int dummy)
11149 {
11150         struct cli_state *cli = NULL;
11151         struct cli_state *cli_posix = NULL;
11152         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11153         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11154         char *mangled_path = NULL;
11155         uint16_t fnum;
11156         fstring name;
11157         fstring alt_name;
11158         NTSTATUS status;
11159
11160         printf("starting mangle-illegal test\n");
11161
11162         if (!torture_open_connection(&cli, 0)) {
11163                 return False;
11164         }
11165
11166         smbXcli_conn_set_sockopt(cli->conn, sockops);
11167
11168         if (!torture_open_connection(&cli_posix, 0)) {
11169                 return false;
11170         }
11171
11172         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11173
11174         status = torture_setup_unix_extensions(cli_posix);
11175         if (!NT_STATUS_IS_OK(status)) {
11176                 return false;
11177         }
11178
11179         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11180         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11181         if (!NT_STATUS_IS_OK(status)) {
11182                 printf("mkdir1 failed : %s\n", nt_errstr(status));
11183                 return False;
11184         }
11185
11186         /*
11187          * Create a file with illegal NTFS characters and test that we
11188          * get a usable mangled name
11189          */
11190
11191         cli_setatr(cli_posix, illegal_fname, 0, 0);
11192         cli_posix_unlink(cli_posix, illegal_fname);
11193
11194         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11195                                 0600, &fnum);
11196         if (!NT_STATUS_IS_OK(status)) {
11197                 printf("POSIX create of %s failed (%s)\n",
11198                        illegal_fname, nt_errstr(status));
11199                 return false;
11200         }
11201
11202         status = cli_close(cli_posix, fnum);
11203         if (!NT_STATUS_IS_OK(status)) {
11204                 printf("close failed (%s)\n", nt_errstr(status));
11205                 return false;
11206         }
11207
11208         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11209         if (!NT_STATUS_IS_OK(status)) {
11210                 d_printf("cli_list failed: %s\n", nt_errstr(status));
11211                 return false;
11212         }
11213
11214         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11215         if (mangled_path == NULL) {
11216                 return false;
11217         }
11218
11219         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11220         if (!NT_STATUS_IS_OK(status)) {
11221                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11222                 TALLOC_FREE(mangled_path);
11223                 return false;
11224         }
11225         TALLOC_FREE(mangled_path);
11226         cli_close(cli, fnum);
11227
11228         cli_setatr(cli_posix, illegal_fname, 0, 0);
11229         cli_posix_unlink(cli_posix, illegal_fname);
11230
11231         /*
11232          * Create a file with a long name and check that we got *no* short name.
11233          */
11234
11235         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11236                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11237                               0, 0, &fnum, NULL);
11238         if (!NT_STATUS_IS_OK(status)) {
11239                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11240                 return false;
11241         }
11242         cli_close(cli, fnum);
11243
11244         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11245         if (!NT_STATUS_IS_OK(status)) {
11246                 d_printf("cli_list failed\n");
11247                 return false;
11248         }
11249
11250         cli_unlink(cli, fname, 0);
11251         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11252
11253         if (!torture_close_connection(cli_posix)) {
11254                 return false;
11255         }
11256
11257         if (!torture_close_connection(cli)) {
11258                 return false;
11259         }
11260
11261         return true;
11262 }
11263
11264 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11265 {
11266         size_t *to_pull = (size_t *)priv;
11267         size_t thistime = *to_pull;
11268
11269         thistime = MIN(thistime, n);
11270         if (thistime == 0) {
11271                 return 0;
11272         }
11273
11274         memset(buf, 0, thistime);
11275         *to_pull -= thistime;
11276         return thistime;
11277 }
11278
11279 static bool run_windows_write(int dummy)
11280 {
11281         struct cli_state *cli1;
11282         uint16_t fnum;
11283         int i;
11284         bool ret = false;
11285         const char *fname = "\\writetest.txt";
11286         struct timeval start_time;
11287         double seconds;
11288         double kbytes;
11289         NTSTATUS status;
11290
11291         printf("starting windows_write test\n");
11292         if (!torture_open_connection(&cli1, 0)) {
11293                 return False;
11294         }
11295
11296         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11297         if (!NT_STATUS_IS_OK(status)) {
11298                 printf("open failed (%s)\n", nt_errstr(status));
11299                 return False;
11300         }
11301
11302         smbXcli_conn_set_sockopt(cli1->conn, sockops);
11303
11304         start_time = timeval_current();
11305
11306         for (i=0; i<torture_numops; i++) {
11307                 uint8_t c = 0;
11308                 off_t start = i * torture_blocksize;
11309                 size_t to_pull = torture_blocksize - 1;
11310
11311                 status = cli_writeall(cli1, fnum, 0, &c,
11312                                       start + torture_blocksize - 1, 1, NULL);
11313                 if (!NT_STATUS_IS_OK(status)) {
11314                         printf("cli_write failed: %s\n", nt_errstr(status));
11315                         goto fail;
11316                 }
11317
11318                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11319                                   null_source, &to_pull);
11320                 if (!NT_STATUS_IS_OK(status)) {
11321                         printf("cli_push returned: %s\n", nt_errstr(status));
11322                         goto fail;
11323                 }
11324         }
11325
11326         seconds = timeval_elapsed(&start_time);
11327         kbytes = (double)torture_blocksize * torture_numops;
11328         kbytes /= 1024;
11329
11330         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11331                (double)seconds, (int)(kbytes/seconds));
11332
11333         ret = true;
11334  fail:
11335         cli_close(cli1, fnum);
11336         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11337         torture_close_connection(cli1);
11338         return ret;
11339 }
11340
11341 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11342 {
11343         size_t max_pdu = 0x1FFFF;
11344
11345         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11346                 max_pdu = 0xFFFFFF;
11347         }
11348
11349         if (smb1cli_conn_signing_is_active(cli->conn)) {
11350                 max_pdu = 0x1FFFF;
11351         }
11352
11353         if (smb1cli_conn_encryption_on(cli->conn)) {
11354                 max_pdu = CLI_BUFFER_SIZE;
11355         }
11356
11357         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11358                 len_requested &= 0xFFFF;
11359         }
11360
11361         return MIN(len_requested,
11362                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11363 }
11364
11365 static bool check_read_call(struct cli_state *cli,
11366                             uint16_t fnum,
11367                             uint8_t *buf,
11368                             size_t len_requested)
11369 {
11370         NTSTATUS status;
11371         struct tevent_req *subreq = NULL;
11372         ssize_t len_read = 0;
11373         size_t len_expected = 0;
11374         struct tevent_context *ev = NULL;
11375
11376         ev = samba_tevent_context_init(talloc_tos());
11377         if (ev == NULL) {
11378                 return false;
11379         }
11380
11381         subreq = cli_read_andx_send(talloc_tos(),
11382                                     ev,
11383                                     cli,
11384                                     fnum,
11385                                     0,
11386                                     len_requested);
11387
11388         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11389                 return false;
11390         }
11391
11392         status = cli_read_andx_recv(subreq, &len_read, &buf);
11393         if (!NT_STATUS_IS_OK(status)) {
11394                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11395                 return false;
11396         }
11397
11398         TALLOC_FREE(subreq);
11399         TALLOC_FREE(ev);
11400
11401         len_expected = calc_expected_return(cli, len_requested);
11402
11403         if (len_expected > 0x10000 && len_read == 0x10000) {
11404                 /* Windows servers only return a max of 0x10000,
11405                    doesn't matter if you set CAP_LARGE_READX in
11406                    the client sessionsetupX call or not. */
11407                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11408                         (unsigned int)len_requested);
11409         } else if (len_read != len_expected) {
11410                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11411                         (unsigned int)len_requested,
11412                         (unsigned int)len_read,
11413                         (unsigned int)len_expected);
11414                 return false;
11415         } else {
11416                 d_printf("Correct read reply.\n");
11417         }
11418
11419         return true;
11420 }
11421
11422 /* Test large readX variants. */
11423 static bool large_readx_tests(struct cli_state *cli,
11424                                 uint16_t fnum,
11425                                 uint8_t *buf)
11426 {
11427         /* A read of 0xFFFF0001 should *always* return 1 byte. */
11428         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11429                 return false;
11430         }
11431         /* A read of 0x10000 should return 0x10000 bytes. */
11432         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
11433                 return false;
11434         }
11435         /* A read of 0x10000 should return 0x10001 bytes. */
11436         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
11437                 return false;
11438         }
11439         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11440            the requested number of bytes. */
11441         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11442                 return false;
11443         }
11444         /* A read of 1MB should return 1MB bytes (on Samba). */
11445         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
11446                 return false;
11447         }
11448
11449         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
11450                 return false;
11451         }
11452         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11453                 return false;
11454         }
11455         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11456                 return false;
11457         }
11458         return true;
11459 }
11460
11461 static bool run_large_readx(int dummy)
11462 {
11463         uint8_t *buf = NULL;
11464         struct cli_state *cli1 = NULL;
11465         struct cli_state *cli2 = NULL;
11466         bool correct = false;
11467         const char *fname = "\\large_readx.dat";
11468         NTSTATUS status;
11469         uint16_t fnum1 = UINT16_MAX;
11470         uint32_t normal_caps = 0;
11471         size_t file_size = 20*1024*1024;
11472         TALLOC_CTX *frame = talloc_stackframe();
11473         size_t i;
11474         struct {
11475                 const char *name;
11476                 enum smb_signing_setting signing_setting;
11477                 enum protocol_types protocol;
11478         } runs[] = {
11479                 {
11480                         .name = "NT1",
11481                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
11482                         .protocol = PROTOCOL_NT1,
11483                 },{
11484                         .name = "NT1 - SIGNING_REQUIRED",
11485                         .signing_setting = SMB_SIGNING_REQUIRED,
11486                         .protocol = PROTOCOL_NT1,
11487                 },
11488         };
11489
11490         printf("starting large_readx test\n");
11491
11492         if (!torture_open_connection(&cli1, 0)) {
11493                 goto out;
11494         }
11495
11496         normal_caps = smb1cli_conn_capabilities(cli1->conn);
11497
11498         if (!(normal_caps & CAP_LARGE_READX)) {
11499                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11500                         (unsigned int)normal_caps);
11501                 goto out;
11502         }
11503
11504         /* Create a file of size 4MB. */
11505         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11506                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11507                         0, 0, &fnum1, NULL);
11508
11509         if (!NT_STATUS_IS_OK(status)) {
11510                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11511                 goto out;
11512         }
11513
11514         /* Write file_size bytes. */
11515         buf = talloc_zero_array(frame, uint8_t, file_size);
11516         if (buf == NULL) {
11517                 goto out;
11518         }
11519
11520         status = cli_writeall(cli1,
11521                               fnum1,
11522                               0,
11523                               buf,
11524                               0,
11525                               file_size,
11526                               NULL);
11527         if (!NT_STATUS_IS_OK(status)) {
11528                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11529                 goto out;
11530         }
11531
11532         status = cli_close(cli1, fnum1);
11533         if (!NT_STATUS_IS_OK(status)) {
11534                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11535                 goto out;
11536         }
11537
11538         fnum1 = UINT16_MAX;
11539
11540         for (i=0; i < ARRAY_SIZE(runs); i++) {
11541                 enum smb_signing_setting saved_signing_setting = signing_state;
11542                 uint16_t fnum2 = -1;
11543
11544                 if (do_encrypt &&
11545                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11546                 {
11547                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11548                         continue;
11549                 }
11550
11551                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11552
11553                 signing_state = runs[i].signing_setting;
11554                 cli2 = open_nbt_connection();
11555                 signing_state = saved_signing_setting;
11556                 if (cli2 == NULL) {
11557                         goto out;
11558                 }
11559
11560                 status = smbXcli_negprot(cli2->conn,
11561                                          cli2->timeout,
11562                                          runs[i].protocol,
11563                                          runs[i].protocol,
11564                                          NULL,
11565                                          NULL,
11566                                          NULL);
11567                 if (!NT_STATUS_IS_OK(status)) {
11568                         goto out;
11569                 }
11570
11571                 status = cli_session_setup_creds(cli2, torture_creds);
11572                 if (!NT_STATUS_IS_OK(status)) {
11573                         goto out;
11574                 }
11575
11576                 status = cli_tree_connect(cli2,
11577                                         share,
11578                                         "?????",
11579                                         password);
11580                 if (!NT_STATUS_IS_OK(status)) {
11581                         goto out;
11582                 }
11583
11584                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11585
11586                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11587
11588                 if (!(normal_caps & CAP_LARGE_READX)) {
11589                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11590                                 (unsigned int)normal_caps);
11591                         goto out;
11592                 }
11593
11594                 if (do_encrypt) {
11595                         if (force_cli_encryption(cli2, share) == false) {
11596                                 goto out;
11597                         }
11598                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11599                         uint16_t major, minor;
11600                         uint32_t caplow, caphigh;
11601
11602                         status = cli_unix_extensions_version(cli2,
11603                                                              &major, &minor,
11604                                                              &caplow, &caphigh);
11605                         if (!NT_STATUS_IS_OK(status)) {
11606                                 goto out;
11607                         }
11608                 }
11609
11610                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11611                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11612                                 0, 0, &fnum2, NULL);
11613                 if (!NT_STATUS_IS_OK(status)) {
11614                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11615                         goto out;
11616                 }
11617
11618                 /* All reads must return less than file_size bytes. */
11619                 if (!large_readx_tests(cli2, fnum2, buf)) {
11620                         goto out;
11621                 }
11622
11623                 status = cli_close(cli2, fnum2);
11624                 if (!NT_STATUS_IS_OK(status)) {
11625                         d_printf("cli_close failed: %s\n", nt_errstr(status));
11626                         goto out;
11627                 }
11628                 fnum2 = -1;
11629
11630                 if (!torture_close_connection(cli2)) {
11631                         goto out;
11632                 }
11633                 cli2 = NULL;
11634         }
11635
11636         correct = true;
11637         printf("Success on large_readx test\n");
11638
11639   out:
11640
11641         if (cli2) {
11642                 if (!torture_close_connection(cli2)) {
11643                         correct = false;
11644                 }
11645         }
11646
11647         if (cli1) {
11648                 if (fnum1 != UINT16_MAX) {
11649                         status = cli_close(cli1, fnum1);
11650                         if (!NT_STATUS_IS_OK(status)) {
11651                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
11652                         }
11653                         fnum1 = UINT16_MAX;
11654                 }
11655
11656                 status = cli_unlink(cli1, fname,
11657                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11658                 if (!NT_STATUS_IS_OK(status)) {
11659                         printf("unlink failed (%s)\n", nt_errstr(status));
11660                 }
11661
11662                 if (!torture_close_connection(cli1)) {
11663                         correct = false;
11664                 }
11665         }
11666
11667         TALLOC_FREE(frame);
11668
11669         printf("finished large_readx test\n");
11670         return correct;
11671 }
11672
11673 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11674                                   const char *mask,
11675                                   void *private_data)
11676 {
11677         uint32_t *p_attr = (uint32_t *)private_data;
11678
11679         if (strequal(finfo->name, test_filename)) {
11680                 *p_attr = finfo->attr;
11681         }
11682
11683         return NT_STATUS_OK;
11684 }
11685
11686 static bool run_msdfs_attribute(int dummy)
11687 {
11688         static struct cli_state *cli;
11689         bool correct = false;
11690         uint32_t attr = 0;
11691         NTSTATUS status;
11692
11693         printf("Starting MSDFS-ATTRIBUTE test\n");
11694
11695         if (test_filename == NULL || test_filename[0] == '\0') {
11696                 printf("MSDFS-ATTRIBUTE test "
11697                         "needs -f filename-of-msdfs-link\n");
11698                 return false;
11699         }
11700
11701         /*
11702          * NB. We use torture_open_connection_flags() not
11703          * torture_open_connection() as the latter forces
11704          * SMB1.
11705          */
11706         if (!torture_open_connection_flags(&cli, 0, 0)) {
11707                 return false;
11708         }
11709
11710         smbXcli_conn_set_sockopt(cli->conn, sockops);
11711
11712         status = cli_list(cli,
11713                         "*",
11714                         FILE_ATTRIBUTE_DIRECTORY,
11715                         msdfs_attribute_list_fn,
11716                         &attr);
11717
11718         if (!NT_STATUS_IS_OK(status)) {
11719                 printf("cli_list failed with %s\n",
11720                         nt_errstr(status));
11721                 goto out;
11722         }
11723         if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11724                 printf("file %s should have "
11725                         "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11726                         test_filename,
11727                         (unsigned int)attr);
11728                 goto out;
11729         }
11730
11731         if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11732                 printf("file %s should have "
11733                         "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11734                         test_filename,
11735                         (unsigned int)attr);
11736                 goto out;
11737         }
11738
11739         correct = true;
11740
11741   out:
11742
11743         torture_close_connection(cli);
11744         return correct;
11745 }
11746
11747 static bool run_cli_echo(int dummy)
11748 {
11749         struct cli_state *cli;
11750         NTSTATUS status;
11751
11752         printf("starting cli_echo test\n");
11753         if (!torture_open_connection(&cli, 0)) {
11754                 return false;
11755         }
11756         smbXcli_conn_set_sockopt(cli->conn, sockops);
11757
11758         status = cli_echo(cli, 5, data_blob_const("hello", 5));
11759
11760         d_printf("cli_echo returned %s\n", nt_errstr(status));
11761
11762         torture_close_connection(cli);
11763         return NT_STATUS_IS_OK(status);
11764 }
11765
11766 static int splice_status(off_t written, void *priv)
11767 {
11768         return true;
11769 }
11770
11771 static bool run_cli_splice(int dummy)
11772 {
11773         uint8_t *buf = NULL;
11774         struct cli_state *cli1 = NULL;
11775         bool correct = false;
11776         const char *fname_src = "\\splice_src.dat";
11777         const char *fname_dst = "\\splice_dst.dat";
11778         NTSTATUS status;
11779         uint16_t fnum1 = UINT16_MAX;
11780         uint16_t fnum2 = UINT16_MAX;
11781         size_t file_size = 2*1024*1024;
11782         size_t splice_size = 1*1024*1024 + 713;
11783         uint8_t digest1[16], digest2[16];
11784         off_t written = 0;
11785         size_t nread = 0;
11786         TALLOC_CTX *frame = talloc_stackframe();
11787
11788         printf("starting cli_splice test\n");
11789
11790         if (!torture_open_connection(&cli1, 0)) {
11791                 goto out;
11792         }
11793
11794         cli_unlink(cli1, fname_src,
11795                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11796         cli_unlink(cli1, fname_dst,
11797                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11798
11799         /* Create a file */
11800         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11801                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11802                         0, 0, &fnum1, NULL);
11803
11804         if (!NT_STATUS_IS_OK(status)) {
11805                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11806                 goto out;
11807         }
11808
11809         /* Write file_size bytes - must be bigger than splice_size. */
11810         buf = talloc_zero_array(frame, uint8_t, file_size);
11811         if (buf == NULL) {
11812                 d_printf("talloc_fail\n");
11813                 goto out;
11814         }
11815
11816         /* Fill it with random numbers. */
11817         generate_random_buffer(buf, file_size);
11818
11819         /* MD5 the first 1MB + 713 bytes. */
11820         gnutls_hash_fast(GNUTLS_DIG_MD5,
11821                          buf,
11822                          splice_size,
11823                          digest1);
11824
11825         status = cli_writeall(cli1,
11826                               fnum1,
11827                               0,
11828                               buf,
11829                               0,
11830                               file_size,
11831                               NULL);
11832         if (!NT_STATUS_IS_OK(status)) {
11833                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11834                 goto out;
11835         }
11836
11837         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11838                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11839                         0, 0, &fnum2, NULL);
11840
11841         if (!NT_STATUS_IS_OK(status)) {
11842                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11843                 goto out;
11844         }
11845
11846         /* Now splice 1MB + 713 bytes. */
11847         status = cli_splice(cli1,
11848                                 cli1,
11849                                 fnum1,
11850                                 fnum2,
11851                                 splice_size,
11852                                 0,
11853                                 0,
11854                                 &written,
11855                                 splice_status,
11856                                 NULL);
11857
11858         if (!NT_STATUS_IS_OK(status)) {
11859                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11860                 goto out;
11861         }
11862
11863         /* Clear the old buffer. */
11864         memset(buf, '\0', file_size);
11865
11866         /* Read the new file. */
11867         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11868         if (!NT_STATUS_IS_OK(status)) {
11869                 d_printf("cli_read failed: %s\n", nt_errstr(status));
11870                 goto out;
11871         }
11872         if (nread != splice_size) {
11873                 d_printf("bad read of 0x%x, should be 0x%x\n",
11874                         (unsigned int)nread,
11875                         (unsigned int)splice_size);
11876                 goto out;
11877         }
11878
11879         /* MD5 the first 1MB + 713 bytes. */
11880         gnutls_hash_fast(GNUTLS_DIG_MD5,
11881                          buf,
11882                          splice_size,
11883                          digest2);
11884
11885         /* Must be the same. */
11886         if (memcmp(digest1, digest2, 16) != 0) {
11887                 d_printf("bad MD5 compare\n");
11888                 goto out;
11889         }
11890
11891         correct = true;
11892         printf("Success on cli_splice test\n");
11893
11894   out:
11895
11896         if (cli1) {
11897                 if (fnum1 != UINT16_MAX) {
11898                         cli_close(cli1, fnum1);
11899                 }
11900                 if (fnum2 != UINT16_MAX) {
11901                         cli_close(cli1, fnum2);
11902                 }
11903
11904                 cli_unlink(cli1, fname_src,
11905                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11906                 cli_unlink(cli1, fname_dst,
11907                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11908
11909                 if (!torture_close_connection(cli1)) {
11910                         correct = false;
11911                 }
11912         }
11913
11914         TALLOC_FREE(frame);
11915         return correct;
11916 }
11917
11918 static bool run_uid_regression_test(int dummy)
11919 {
11920         static struct cli_state *cli;
11921         int16_t old_vuid;
11922         int32_t old_cnum;
11923         bool correct = True;
11924         struct smbXcli_tcon *tcon_copy = NULL;
11925         NTSTATUS status;
11926
11927         printf("starting uid regression test\n");
11928
11929         if (!torture_open_connection(&cli, 0)) {
11930                 return False;
11931         }
11932
11933         smbXcli_conn_set_sockopt(cli->conn, sockops);
11934
11935         /* Ok - now save then logoff our current user. */
11936         old_vuid = cli_state_get_uid(cli);
11937
11938         status = cli_ulogoff(cli);
11939         if (!NT_STATUS_IS_OK(status)) {
11940                 d_printf("(%s) cli_ulogoff failed: %s\n",
11941                          __location__, nt_errstr(status));
11942                 correct = false;
11943                 goto out;
11944         }
11945
11946         cli_state_set_uid(cli, old_vuid);
11947
11948         /* Try an operation. */
11949         status = cli_mkdir(cli, "\\uid_reg_test");
11950         if (NT_STATUS_IS_OK(status)) {
11951                 d_printf("(%s) cli_mkdir succeeded\n",
11952                          __location__);
11953                 correct = false;
11954                 goto out;
11955         } else {
11956                 /* Should be bad uid. */
11957                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11958                                  NT_STATUS_USER_SESSION_DELETED)) {
11959                         correct = false;
11960                         goto out;
11961                 }
11962         }
11963
11964         old_cnum = cli_state_get_tid(cli);
11965         /*
11966          * This is an SMB1-only test.
11967          * Copy the tcon, not "save/restore".
11968          *
11969          * In SMB1 the cli_tdis() below frees
11970          * cli->smb1.tcon so we need a copy
11971          * of the struct to put back for the
11972          * second tdis call with invalid vuid.
11973          *
11974          * This is a test-only hack. Real client code
11975          * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11976          */
11977         tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11978         if (tcon_copy == NULL) {
11979                 correct = false;
11980                 goto out;
11981         }
11982
11983         /* Now try a SMBtdis with the invalid vuid set to zero. */
11984         cli_state_set_uid(cli, 0);
11985
11986         /* This should succeed. */
11987         status = cli_tdis(cli);
11988
11989         if (NT_STATUS_IS_OK(status)) {
11990                 d_printf("First tdis with invalid vuid should succeed.\n");
11991         } else {
11992                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11993                 correct = false;
11994                 cli->smb1.tcon = tcon_copy;
11995                 goto out;
11996         }
11997
11998         cli->smb1.tcon = tcon_copy;
11999         cli_state_set_uid(cli, old_vuid);
12000         cli_state_set_tid(cli, old_cnum);
12001
12002         /* This should fail. */
12003         status = cli_tdis(cli);
12004         if (NT_STATUS_IS_OK(status)) {
12005                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12006                 correct = false;
12007                 goto out;
12008         } else {
12009                 /* Should be bad tid. */
12010                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12011                                 NT_STATUS_NETWORK_NAME_DELETED)) {
12012                         correct = false;
12013                         goto out;
12014                 }
12015         }
12016
12017         cli_rmdir(cli, "\\uid_reg_test");
12018
12019   out:
12020
12021         cli_shutdown(cli);
12022         return correct;
12023 }
12024
12025
12026 static const char *illegal_chars = "*\\/?<>|\":";
12027 static char force_shortname_chars[] = " +,.[];=\177";
12028
12029 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12030                              const char *mask, void *state)
12031 {
12032         struct cli_state *pcli = (struct cli_state *)state;
12033         fstring fname;
12034         NTSTATUS status = NT_STATUS_OK;
12035
12036         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12037
12038         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12039                 return NT_STATUS_OK;
12040
12041         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12042                 status = cli_rmdir(pcli, fname);
12043                 if (!NT_STATUS_IS_OK(status)) {
12044                         printf("del_fn: failed to rmdir %s\n,", fname );
12045                 }
12046         } else {
12047                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12048                 if (!NT_STATUS_IS_OK(status)) {
12049                         printf("del_fn: failed to unlink %s\n,", fname );
12050                 }
12051         }
12052         return status;
12053 }
12054
12055 struct sn_state {
12056         int matched;
12057         int i;
12058         bool val;
12059 };
12060
12061 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12062                               const char *name, void *state)
12063 {
12064         struct sn_state *s = (struct sn_state  *)state;
12065         int i = s->i;
12066
12067 #if 0
12068         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12069                 i, finfo->name, finfo->short_name);
12070 #endif
12071
12072         if (strchr(force_shortname_chars, i)) {
12073                 if (!finfo->short_name) {
12074                         /* Shortname not created when it should be. */
12075                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12076                                 __location__, finfo->name, i);
12077                         s->val = true;
12078                 }
12079         } else if (finfo->short_name){
12080                 /* Shortname created when it should not be. */
12081                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12082                         __location__, finfo->short_name, finfo->name);
12083                 s->val = true;
12084         }
12085         s->matched += 1;
12086         return NT_STATUS_OK;
12087 }
12088
12089 static bool run_shortname_test(int dummy)
12090 {
12091         static struct cli_state *cli;
12092         bool correct = True;
12093         int i;
12094         struct sn_state s;
12095         char fname[40];
12096         NTSTATUS status;
12097
12098         printf("starting shortname test\n");
12099
12100         if (!torture_open_connection(&cli, 0)) {
12101                 return False;
12102         }
12103
12104         smbXcli_conn_set_sockopt(cli->conn, sockops);
12105
12106         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12107         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12108         cli_rmdir(cli, "\\shortname");
12109
12110         status = cli_mkdir(cli, "\\shortname");
12111         if (!NT_STATUS_IS_OK(status)) {
12112                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12113                         __location__, nt_errstr(status));
12114                 correct = false;
12115                 goto out;
12116         }
12117
12118         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12119                 correct = false;
12120                 goto out;
12121         }
12122         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12123                 correct = false;
12124                 goto out;
12125         }
12126
12127         s.val = false;
12128
12129         for (i = 32; i < 128; i++) {
12130                 uint16_t fnum = (uint16_t)-1;
12131
12132                 s.i = i;
12133
12134                 if (strchr(illegal_chars, i)) {
12135                         continue;
12136                 }
12137                 fname[15] = i;
12138
12139                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12140                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
12141                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12142                 if (!NT_STATUS_IS_OK(status)) {
12143                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
12144                                 __location__, fname, nt_errstr(status));
12145                         correct = false;
12146                         goto out;
12147                 }
12148                 cli_close(cli, fnum);
12149
12150                 s.matched = 0;
12151                 status = cli_list(cli, "\\shortname\\test*.*", 0,
12152                                   shortname_list_fn, &s);
12153                 if (s.matched != 1) {
12154                         d_printf("(%s) failed to list %s: %s\n",
12155                                 __location__, fname, nt_errstr(status));
12156                         correct = false;
12157                         goto out;
12158                 }
12159
12160                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12161                 if (!NT_STATUS_IS_OK(status)) {
12162                         d_printf("(%s) failed to delete %s: %s\n",
12163                                 __location__, fname, nt_errstr(status));
12164                         correct = false;
12165                         goto out;
12166                 }
12167
12168                 if (s.val) {
12169                         correct = false;
12170                         goto out;
12171                 }
12172         }
12173
12174   out:
12175
12176         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12177         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12178         cli_rmdir(cli, "\\shortname");
12179         torture_close_connection(cli);
12180         return correct;
12181 }
12182
12183 TLDAPRC callback_code;
12184
12185 static void pagedsearch_cb(struct tevent_req *req)
12186 {
12187         TLDAPRC rc;
12188         struct tldap_message *msg;
12189         char *dn;
12190
12191         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12192         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12193                 d_printf("tldap_search_paged_recv failed: %s\n",
12194                          tldap_rc2string(rc));
12195                 callback_code = rc;
12196                 return;
12197         }
12198         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12199                 TALLOC_FREE(msg);
12200                 return;
12201         }
12202         if (!tldap_entry_dn(msg, &dn)) {
12203                 d_printf("tldap_entry_dn failed\n");
12204                 return;
12205         }
12206         d_printf("%s\n", dn);
12207         TALLOC_FREE(msg);
12208 }
12209
12210 enum tldap_extended_val {
12211         EXTENDED_ZERO = 0,
12212         EXTENDED_ONE = 1,
12213         EXTENDED_NONE = 2,
12214 };
12215
12216 /*
12217  * Construct an extended dn control with either no value, 0 or 1
12218  *
12219  * No value and 0 are equivalent (non-hyphenated GUID)
12220  * 1 has the hyphenated GUID
12221  */
12222 static struct tldap_control *
12223 tldap_build_extended_control(enum tldap_extended_val val)
12224 {
12225         struct tldap_control empty_control;
12226         struct asn1_data *data;
12227
12228         ZERO_STRUCT(empty_control);
12229
12230         if (val != EXTENDED_NONE) {
12231                 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12232
12233                 if (!data) {
12234                         return NULL;
12235                 }
12236
12237                 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12238                         return NULL;
12239                 }
12240
12241                 if (!asn1_write_Integer(data, (int)val)) {
12242                         return NULL;
12243                 }
12244
12245                 if (!asn1_pop_tag(data)) {
12246                         return NULL;
12247                 }
12248
12249                 if (!asn1_blob(data, &empty_control.value)) {
12250                         return NULL;
12251                 }
12252         }
12253
12254         empty_control.oid = "1.2.840.113556.1.4.529";
12255         empty_control.critical = true;
12256
12257         return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12258
12259 }
12260
12261 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12262                                       enum tldap_extended_val control_val)
12263 {
12264         struct tldap_control *control = tldap_build_extended_control(control_val);
12265         char *dn = NULL;
12266         struct tldap_message **msg;
12267         TLDAPRC rc;
12268
12269         rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12270                           "(objectClass=*)", NULL, 0, 0,
12271                           control, 1, NULL,
12272                           0, 0, 0, 0, talloc_tos(), &msg);
12273         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12274                 d_printf("tldap_search for domain DN failed: %s\n",
12275                          tldap_errstr(talloc_tos(), ld, rc));
12276                 return false;
12277         }
12278
12279         if (!tldap_entry_dn(msg[0], &dn)) {
12280                 d_printf("tldap_search domain DN fetch failed: %s\n",
12281                          tldap_errstr(talloc_tos(), ld, rc));
12282                 return false;
12283         }
12284
12285         d_printf("%s\n", dn);
12286         {
12287                 uint32_t time_low;
12288                 uint32_t time_mid, time_hi_and_version;
12289                 uint32_t clock_seq[2];
12290                 uint32_t node[6];
12291                 char next;
12292
12293                 switch (control_val) {
12294                 case EXTENDED_NONE:
12295                 case EXTENDED_ZERO:
12296                         /*
12297                          * When reading GUIDs with hyphens, scanf will treat
12298                          * hyphen as a hex character (and counts as part of the
12299                          * width). This creates leftover GUID string which we
12300                          * check will for with 'next' and closing '>'.
12301                          */
12302                         if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12303                                          &time_low, &time_mid,
12304                                          &time_hi_and_version, &clock_seq[0],
12305                                          &clock_seq[1], &node[0], &node[1],
12306                                          &node[2], &node[3], &node[4],
12307                                          &node[5], &next)) {
12308                                 /* This GUID is good */
12309                         } else {
12310                                 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12311                                 return false;
12312                         }
12313
12314                         break;
12315                 case EXTENDED_ONE:
12316                         if (12 == sscanf(dn,
12317                                          "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12318                                          &time_low, &time_mid,
12319                                          &time_hi_and_version, &clock_seq[0],
12320                                          &clock_seq[1], &node[0], &node[1],
12321                                          &node[2], &node[3], &node[4],
12322                                          &node[5], &next)) {
12323                                 /* This GUID is good */
12324                         } else {
12325                                 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12326                                 return false;
12327                         }
12328
12329                         break;
12330                 default:
12331                         return false;
12332                 }
12333         }
12334
12335         return true;
12336 }
12337
12338 static bool run_tldap(int dummy)
12339 {
12340         struct tldap_context *ld;
12341         int fd;
12342         TLDAPRC rc;
12343         NTSTATUS status;
12344         struct sockaddr_storage addr;
12345         struct tevent_context *ev;
12346         struct tevent_req *req;
12347         char *basedn;
12348         const char *filter;
12349
12350         if (!resolve_name(host, &addr, 0, false)) {
12351                 d_printf("could not find host %s\n", host);
12352                 return false;
12353         }
12354         status = open_socket_out(&addr, 389, 9999, &fd);
12355         if (!NT_STATUS_IS_OK(status)) {
12356                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12357                 return false;
12358         }
12359
12360         ld = tldap_context_create(talloc_tos(), fd);
12361         if (ld == NULL) {
12362                 close(fd);
12363                 d_printf("tldap_context_create failed\n");
12364                 return false;
12365         }
12366
12367         rc = tldap_fetch_rootdse(ld);
12368         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12369                 d_printf("tldap_fetch_rootdse failed: %s\n",
12370                          tldap_errstr(talloc_tos(), ld, rc));
12371                 return false;
12372         }
12373
12374         basedn = tldap_talloc_single_attribute(
12375                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12376         if (basedn == NULL) {
12377                 d_printf("no defaultNamingContext\n");
12378                 return false;
12379         }
12380         d_printf("defaultNamingContext: %s\n", basedn);
12381
12382         ev = samba_tevent_context_init(talloc_tos());
12383         if (ev == NULL) {
12384                 d_printf("tevent_context_init failed\n");
12385                 return false;
12386         }
12387
12388         rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12389                                loadparm_init_s3(talloc_tos(),
12390                                                 loadparm_s3_helpers()),
12391                                GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12392
12393         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12394                 d_printf("tldap_gensec_bind failed\n");
12395                 return false;
12396         }
12397
12398         callback_code = TLDAP_SUCCESS;
12399
12400         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12401                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
12402                                       NULL, 0, 0,
12403                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
12404         if (req == NULL) {
12405                 d_printf("tldap_search_paged_send failed\n");
12406                 return false;
12407         }
12408         tevent_req_set_callback(req, pagedsearch_cb, NULL);
12409
12410         tevent_req_poll(req, ev);
12411
12412         TALLOC_FREE(req);
12413
12414         rc = callback_code;
12415
12416         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12417                 d_printf("tldap_search with paging failed: %s\n",
12418                          tldap_errstr(talloc_tos(), ld, rc));
12419                 return false;
12420         }
12421
12422         /* test search filters against rootDSE */
12423         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12424                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12425
12426         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12427                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12428                           talloc_tos(), NULL);
12429         if (!TLDAP_RC_IS_SUCCESS(rc)) {
12430                 d_printf("tldap_search with complex filter failed: %s\n",
12431                          tldap_errstr(talloc_tos(), ld, rc));
12432                 return false;
12433         }
12434
12435         /*
12436          * Tests to check for regression of:
12437          *
12438          * https://bugzilla.samba.org/show_bug.cgi?id=14029
12439          *
12440          * TLDAP used here to pick apart the original string DN (with GUID)
12441          */
12442         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12443                 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12444                          tldap_errstr(talloc_tos(), ld, rc));
12445                 return false;
12446         }
12447         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12448                 d_printf("tldap_search with extended dn (0) failed: %s\n",
12449                          tldap_errstr(talloc_tos(), ld, rc));
12450                 return false;
12451         }
12452         if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12453                 d_printf("tldap_search with extended dn (1) failed: %s\n",
12454                          tldap_errstr(talloc_tos(), ld, rc));
12455                 return false;
12456         }
12457
12458         TALLOC_FREE(ld);
12459         return true;
12460 }
12461
12462 /* Torture test to ensure no regression of :
12463 https://bugzilla.samba.org/show_bug.cgi?id=7084
12464 */
12465
12466 static bool run_dir_createtime(int dummy)
12467 {
12468         struct cli_state *cli;
12469         const char *dname = "\\testdir_createtime";
12470         const char *fname = "\\testdir_createtime\\testfile";
12471         NTSTATUS status;
12472         struct timespec create_time;
12473         struct timespec create_time1;
12474         uint16_t fnum;
12475         bool ret = false;
12476         uint64_t ino;
12477
12478         if (!torture_open_connection(&cli, 0)) {
12479                 return false;
12480         }
12481
12482         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12483                 /* Ensure ino is zero, SMB2 gets a real one. */
12484                 ino = 0;
12485         } else {
12486                 /* Ensure ino is -1, SMB1 never gets a real one. */
12487                 ino = (uint64_t)-1;
12488         }
12489
12490         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12491         cli_rmdir(cli, dname);
12492
12493         status = cli_mkdir(cli, dname);
12494         if (!NT_STATUS_IS_OK(status)) {
12495                 printf("mkdir failed: %s\n", nt_errstr(status));
12496                 goto out;
12497         }
12498
12499         status = cli_qpathinfo2(cli,
12500                                 dname,
12501                                 &create_time,
12502                                 NULL,
12503                                 NULL,
12504                                 NULL,
12505                                 NULL,
12506                                 NULL,
12507                                 &ino,
12508                                 NULL);
12509         if (!NT_STATUS_IS_OK(status)) {
12510                 printf("cli_qpathinfo2 returned %s\n",
12511                        nt_errstr(status));
12512                 goto out;
12513         }
12514
12515         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12516                 /* SMB2 should always return an inode. */
12517                 if (ino == 0) {
12518                         printf("SMB2 bad inode (0)\n");
12519                         goto out;
12520                 }
12521         } else {
12522                 /* SMB1 must always return zero here. */
12523                 if (ino != 0) {
12524                         printf("SMB1 bad inode (!0)\n");
12525                         goto out;
12526                 }
12527         }
12528
12529         /* Sleep 3 seconds, then create a file. */
12530         sleep(3);
12531
12532         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12533                          DENY_NONE, &fnum);
12534         if (!NT_STATUS_IS_OK(status)) {
12535                 printf("cli_openx failed: %s\n", nt_errstr(status));
12536                 goto out;
12537         }
12538
12539         status = cli_qpathinfo2(cli,
12540                                 dname,
12541                                 &create_time1,
12542                                 NULL,
12543                                 NULL,
12544                                 NULL,
12545                                 NULL,
12546                                 NULL,
12547                                 NULL,
12548                                 NULL);
12549         if (!NT_STATUS_IS_OK(status)) {
12550                 printf("cli_qpathinfo2 (2) returned %s\n",
12551                        nt_errstr(status));
12552                 goto out;
12553         }
12554
12555         if (timespec_compare(&create_time1, &create_time)) {
12556                 printf("run_dir_createtime: create time was updated (error)\n");
12557         } else {
12558                 printf("run_dir_createtime: create time was not updated (correct)\n");
12559                 ret = true;
12560         }
12561
12562   out:
12563
12564         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12565         cli_rmdir(cli, dname);
12566         if (!torture_close_connection(cli)) {
12567                 ret = false;
12568         }
12569         return ret;
12570 }
12571
12572
12573 static bool run_streamerror(int dummy)
12574 {
12575         struct cli_state *cli;
12576         const char *dname = "\\testdir_streamerror";
12577         const char *streamname =
12578                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12579         NTSTATUS status;
12580         time_t change_time, access_time, write_time;
12581         off_t size;
12582         uint16_t fnum;
12583         uint32_t attr;
12584         bool ret = true;
12585
12586         if (!torture_open_connection(&cli, 0)) {
12587                 return false;
12588         }
12589
12590         torture_deltree(cli, dname);
12591
12592         status = cli_mkdir(cli, dname);
12593         if (!NT_STATUS_IS_OK(status)) {
12594                 printf("mkdir failed: %s\n", nt_errstr(status));
12595                 return false;
12596         }
12597
12598         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12599                                 &write_time, &size, &attr);
12600         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12601                 printf("pathinfo returned %s, expected "
12602                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12603                        nt_errstr(status));
12604                 ret = false;
12605         }
12606
12607         status = cli_ntcreate(cli, streamname, 0x16,
12608                               FILE_READ_DATA|FILE_READ_EA|
12609                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12610                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12611                               FILE_OPEN, 0, 0, &fnum, NULL);
12612
12613         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12614                 printf("ntcreate returned %s, expected "
12615                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12616                        nt_errstr(status));
12617                 ret = false;
12618         }
12619
12620
12621         cli_rmdir(cli, dname);
12622         return ret;
12623 }
12624
12625 struct pidtest_state {
12626         bool success;
12627         uint16_t vwv[1];
12628         DATA_BLOB data;
12629 };
12630
12631 static void pid_echo_done(struct tevent_req *subreq);
12632
12633 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12634                         struct tevent_context *ev,
12635                         struct cli_state *cli)
12636 {
12637         struct tevent_req *req, *subreq;
12638         struct pidtest_state *state;
12639
12640         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12641         if (req == NULL) {
12642                 return NULL;
12643         }
12644
12645         SSVAL(state->vwv, 0, 1);
12646         state->data = data_blob_const("hello", 5);
12647
12648         subreq = smb1cli_req_send(state,
12649                                 ev,
12650                                 cli->conn,
12651                                 SMBecho,
12652                                 0, 0, /* *_flags */
12653                                 0, 0, /* *_flags2 */
12654                                 cli->timeout,
12655                                 0xDEADBEEF, /* pid */
12656                                 NULL, /* tcon */
12657                                 NULL, /* session */
12658                                 ARRAY_SIZE(state->vwv), state->vwv,
12659                                 state->data.length, state->data.data);
12660
12661         if (tevent_req_nomem(subreq, req)) {
12662                 return tevent_req_post(req, ev);
12663         }
12664         tevent_req_set_callback(subreq, pid_echo_done, req);
12665         return req;
12666 }
12667
12668 static void pid_echo_done(struct tevent_req *subreq)
12669 {
12670         struct tevent_req *req = tevent_req_callback_data(
12671                 subreq, struct tevent_req);
12672         struct pidtest_state *state = tevent_req_data(
12673                 req, struct pidtest_state);
12674         NTSTATUS status;
12675         uint32_t num_bytes;
12676         uint8_t *bytes = NULL;
12677         struct iovec *recv_iov = NULL;
12678         uint8_t *phdr = NULL;
12679         uint16_t pidlow = 0;
12680         uint16_t pidhigh = 0;
12681         struct smb1cli_req_expected_response expected[] = {
12682         {
12683                 .status = NT_STATUS_OK,
12684                 .wct    = 1,
12685         },
12686         };
12687
12688         status = smb1cli_req_recv(subreq, state,
12689                                 &recv_iov,
12690                                 &phdr,
12691                                 NULL, /* pwct */
12692                                 NULL, /* pvwv */
12693                                 NULL, /* pvwv_offset */
12694                                 &num_bytes,
12695                                 &bytes,
12696                                 NULL, /* pbytes_offset */
12697                                 NULL, /* pinbuf */
12698                                 expected, ARRAY_SIZE(expected));
12699
12700         TALLOC_FREE(subreq);
12701
12702         if (!NT_STATUS_IS_OK(status)) {
12703                 tevent_req_nterror(req, status);
12704                 return;
12705         }
12706
12707         if (num_bytes != state->data.length) {
12708                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12709                 return;
12710         }
12711
12712         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12713                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12714                 return;
12715         }
12716
12717         /* Check pid low/high == DEADBEEF */
12718         pidlow = SVAL(phdr, HDR_PID);
12719         if (pidlow != 0xBEEF){
12720                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12721                         (unsigned int)pidlow);
12722                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12723                 return;
12724         }
12725         pidhigh = SVAL(phdr, HDR_PIDHIGH);
12726         if (pidhigh != 0xDEAD){
12727                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12728                         (unsigned int)pidhigh);
12729                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12730                 return;
12731         }
12732
12733         tevent_req_done(req);
12734 }
12735
12736 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12737 {
12738         return tevent_req_simple_recv_ntstatus(req);
12739 }
12740
12741 static bool run_pidhigh(int dummy)
12742 {
12743         bool success = false;
12744         struct cli_state *cli = NULL;
12745         NTSTATUS status;
12746         struct tevent_context *ev = NULL;
12747         struct tevent_req *req = NULL;
12748         TALLOC_CTX *frame = talloc_stackframe();
12749
12750         printf("starting pid high test\n");
12751         if (!torture_open_connection(&cli, 0)) {
12752                 return false;
12753         }
12754         smbXcli_conn_set_sockopt(cli->conn, sockops);
12755
12756         ev = samba_tevent_context_init(frame);
12757         if (ev == NULL) {
12758                 goto fail;
12759         }
12760
12761         req = pid_echo_send(frame, ev, cli);
12762         if (req == NULL) {
12763                 goto fail;
12764         }
12765
12766         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12767                 goto fail;
12768         }
12769
12770         status = pid_echo_recv(req);
12771         if (NT_STATUS_IS_OK(status)) {
12772                 printf("pid high test ok\n");
12773                 success = true;
12774         }
12775
12776  fail:
12777
12778         TALLOC_FREE(frame);
12779         torture_close_connection(cli);
12780         return success;
12781 }
12782
12783 /*
12784   Test Windows open on a bad POSIX symlink.
12785  */
12786 static bool run_symlink_open_test(int dummy)
12787 {
12788         static struct cli_state *cli;
12789         const char *fname = "non_existant_file";
12790         const char *sname = "dangling_symlink";
12791         uint16_t fnum = (uint16_t)-1;
12792         bool correct = false;
12793         NTSTATUS status;
12794         TALLOC_CTX *frame = NULL;
12795
12796         frame = talloc_stackframe();
12797
12798         printf("Starting Windows bad symlink open test\n");
12799
12800         if (!torture_open_connection(&cli, 0)) {
12801                 TALLOC_FREE(frame);
12802                 return false;
12803         }
12804
12805         smbXcli_conn_set_sockopt(cli->conn, sockops);
12806
12807         status = torture_setup_unix_extensions(cli);
12808         if (!NT_STATUS_IS_OK(status)) {
12809                 TALLOC_FREE(frame);
12810                 return false;
12811         }
12812
12813         /* Ensure nothing exists. */
12814         cli_setatr(cli, fname, 0, 0);
12815         cli_posix_unlink(cli, fname);
12816         cli_setatr(cli, sname, 0, 0);
12817         cli_posix_unlink(cli, sname);
12818
12819         /* Create a symlink pointing nowhere. */
12820         status = cli_posix_symlink(cli, fname, sname);
12821         if (!NT_STATUS_IS_OK(status)) {
12822                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12823                         sname,
12824                         fname,
12825                         nt_errstr(status));
12826                 goto out;
12827         }
12828
12829         /* Now ensure that a Windows open doesn't hang. */
12830         status = cli_ntcreate(cli,
12831                         sname,
12832                         0,
12833                         FILE_READ_DATA|FILE_WRITE_DATA,
12834                         0,
12835                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12836                         FILE_OPEN_IF,
12837                         0x0,
12838                         0x0,
12839                         &fnum,
12840                         NULL);
12841
12842         /*
12843          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12844          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12845          * we use O_NOFOLLOW on the server or not.
12846          */
12847         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12848             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12849         {
12850                 correct = true;
12851         } else {
12852                 printf("cli_ntcreate of %s returned %s - should return"
12853                                 " either (%s) or (%s)\n",
12854                         sname,
12855                         nt_errstr(status),
12856                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12857                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12858                 goto out;
12859         }
12860
12861         correct = true;
12862
12863   out:
12864
12865         if (fnum != (uint16_t)-1) {
12866                 cli_close(cli, fnum);
12867                 fnum = (uint16_t)-1;
12868         }
12869
12870         cli_setatr(cli, sname, 0, 0);
12871         cli_posix_unlink(cli, sname);
12872         cli_setatr(cli, fname, 0, 0);
12873         cli_posix_unlink(cli, fname);
12874
12875         if (!torture_close_connection(cli)) {
12876                 correct = false;
12877         }
12878
12879         TALLOC_FREE(frame);
12880         return correct;
12881 }
12882
12883 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12884                                         const char *name,
12885                                         void *state)
12886 {
12887         char **mangled_name_return = (char **)state;
12888         bool is_mangled = strchr(finfo->name, '~');
12889
12890         if (is_mangled) {
12891                 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12892                 if (*mangled_name_return == NULL) {
12893                         return NT_STATUS_NO_MEMORY;
12894                 }
12895         }
12896         return NT_STATUS_OK;
12897 }
12898
12899 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12900 {
12901         static struct cli_state *cli_posix = NULL;
12902         static struct cli_state *cli = NULL;
12903         uint16_t fnum = (uint16_t)-1;
12904         bool correct = false;
12905         const char *dname = "smb1_wild_mangle_unlink";
12906         const char *aname = "smb1_wild_mangle_unlink/a";
12907         const char *star_name = "smb1_wild_mangle_unlink/*";
12908         char *windows_unlink_name = NULL;
12909         char *mangled_name = NULL;
12910         NTSTATUS status;
12911
12912         printf("Starting SMB1 wild mangle unlink test\n");
12913
12914         /* Open a Windows connection. */
12915         if (!torture_open_connection(&cli, 0)) {
12916                 return false;
12917         }
12918
12919         smbXcli_conn_set_sockopt(cli->conn, sockops);
12920
12921         /* Open a POSIX connection. */
12922         if (!torture_open_connection(&cli_posix, 0)) {
12923                 goto out;
12924         }
12925
12926         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12927
12928         status = torture_setup_unix_extensions(cli_posix);
12929         if (!NT_STATUS_IS_OK(status)) {
12930                 printf("server doesn't support POSIX\n");
12931                 goto out;
12932         }
12933
12934         /* Start fresh. */
12935         torture_deltree(cli, dname);
12936
12937         /*
12938          * Create two files - 'a' and '*'.
12939          * We need POSIX extensions for this as '*'
12940          * is not a valid Windows name.
12941          */
12942
12943         status = cli_mkdir(cli, dname);
12944         if (!NT_STATUS_IS_OK(status)) {
12945                 printf("cli_mkdir of %s returned %s\n",
12946                         dname,
12947                         nt_errstr(status));
12948                 goto out;
12949         }
12950
12951         status = cli_posix_open(cli_posix,
12952                                 aname,
12953                                 O_RDWR|O_CREAT|O_EXCL,
12954                                 0660,
12955                                 &fnum);
12956         if (!NT_STATUS_IS_OK(status)) {
12957                 printf("cli_posix_open (create) of %s returned %s\n",
12958                         aname,
12959                         nt_errstr(status));
12960                 goto out;
12961         }
12962         status = cli_close(cli_posix, fnum);
12963         if (!NT_STATUS_IS_OK(status)) {
12964                 goto out;
12965         }
12966         status = cli_posix_open(cli_posix,
12967                                 star_name,
12968                                 O_RDWR|O_CREAT|O_EXCL,
12969                                 0660,
12970                                 &fnum);
12971         if (!NT_STATUS_IS_OK(status)) {
12972                 printf("cli_posix_open (create) of %s returned %s\n",
12973                         star_name,
12974                         nt_errstr(status));
12975                 goto out;
12976         }
12977         status = cli_close(cli_posix, fnum);
12978         if (!NT_STATUS_IS_OK(status)) {
12979                 goto out;
12980         }
12981
12982         status = cli_list(cli,
12983                         star_name,
12984                         0,
12985                         smb1_wild_mangle_list_fn,
12986                         &mangled_name);
12987         if (!NT_STATUS_IS_OK(status)) {
12988                 printf("cli_list of %s returned %s\n",
12989                         star_name,
12990                         nt_errstr(status));
12991                 goto out;
12992         }
12993
12994         if (mangled_name == NULL) {
12995                 goto out;
12996         }
12997
12998         printf("mangled_name = %s\n",
12999                 mangled_name);
13000
13001         /*
13002          * Try a Windows unlink with the mangled name.
13003          * This should *NOT* unlink the 'a' name.
13004          */
13005
13006         windows_unlink_name = talloc_asprintf(cli_posix,
13007                                         "%s\\%s",
13008                                         dname,
13009                                         mangled_name);
13010
13011         status = cli_unlink(cli, windows_unlink_name, 0);
13012         if (!NT_STATUS_IS_OK(status)) {
13013                 printf("cli_unlink of %s returned %s\n",
13014                         windows_unlink_name,
13015                         nt_errstr(status));
13016                 goto out;
13017         }
13018
13019         /* Does 'a' still exist ? */
13020         status = cli_posix_open(cli_posix,
13021                                 aname,
13022                                 O_RDONLY,
13023                                 0,
13024                                 &fnum);
13025         if (!NT_STATUS_IS_OK(status)) {
13026                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13027                         aname,
13028                         nt_errstr(status));
13029                 goto out;
13030         }
13031
13032         status = cli_close(cli_posix, fnum);
13033         if (!NT_STATUS_IS_OK(status)) {
13034                 goto out;
13035         }
13036
13037         correct = true;
13038
13039   out:
13040
13041         TALLOC_FREE(windows_unlink_name);
13042         TALLOC_FREE(mangled_name);
13043
13044         if (cli != NULL) {
13045                 torture_deltree(cli, dname);
13046                 torture_close_connection(cli);
13047         }
13048
13049         if (cli_posix != NULL) {
13050                 torture_close_connection(cli_posix);
13051         }
13052
13053         return correct;
13054 }
13055
13056 static bool run_smb1_wild_mangle_rename_test(int dummy)
13057 {
13058         static struct cli_state *cli_posix = NULL;
13059         static struct cli_state *cli = NULL;
13060         uint16_t fnum = (uint16_t)-1;
13061         bool correct = false;
13062         const char *dname = "smb1_wild_mangle_rename";
13063         const char *fooname = "smb1_wild_mangle_rename/foo";
13064         const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13065         const char *wild_name = "smb1_wild_mangle_rename/*";
13066         char *windows_rename_src = NULL;
13067         const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13068         char *mangled_name = NULL;
13069         NTSTATUS status;
13070
13071         printf("Starting SMB1 wild mangle rename test\n");
13072
13073         if (!torture_open_connection(&cli_posix, 0)) {
13074                 return false;
13075         }
13076
13077         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13078
13079         status = torture_setup_unix_extensions(cli_posix);
13080         if (!NT_STATUS_IS_OK(status)) {
13081                 printf("server doesn't support POSIX\n");
13082                 return false;
13083         }
13084
13085         /* Open a Windows connection. */
13086         if (!torture_open_connection(&cli, 0)) {
13087                 goto out;
13088         }
13089
13090         smbXcli_conn_set_sockopt(cli->conn, sockops);
13091
13092         /* Ensure we start from fresh. */
13093         torture_deltree(cli, dname);
13094
13095         /*
13096          * Create two files - 'foo' and 'fo*'.
13097          * We need POSIX extensions for this as 'fo*'
13098          * is not a valid Windows name.
13099          */
13100
13101         status = cli_posix_mkdir(cli_posix, dname, 0770);
13102         if (!NT_STATUS_IS_OK(status)) {
13103                 printf("cli_posix_mkdir of %s returned %s\n",
13104                         dname,
13105                         nt_errstr(status));
13106                 goto out;
13107         }
13108
13109         status = cli_posix_open(cli_posix,
13110                                 fooname,
13111                                 O_RDWR|O_CREAT|O_EXCL,
13112                                 0660,
13113                                 &fnum);
13114         if (!NT_STATUS_IS_OK(status)) {
13115                 printf("cli_posix_open (create) of %s returned %s\n",
13116                         fooname,
13117                         nt_errstr(status));
13118                 goto out;
13119         }
13120         status = cli_close(cli_posix, fnum);
13121         if (!NT_STATUS_IS_OK(status)) {
13122                 goto out;
13123         }
13124         status = cli_posix_open(cli_posix,
13125                                 foostar_name,
13126                                 O_RDWR|O_CREAT|O_EXCL,
13127                                 0660,
13128                                 &fnum);
13129         if (!NT_STATUS_IS_OK(status)) {
13130                 printf("cli_posix_open (create) of %s returned %s\n",
13131                         foostar_name,
13132                         nt_errstr(status));
13133                 goto out;
13134         }
13135         status = cli_close(cli_posix, fnum);
13136         if (!NT_STATUS_IS_OK(status)) {
13137                 goto out;
13138         }
13139
13140         /*
13141          * Get the mangled name. We can re-use the
13142          * previous smb1_wild_mangle_list_fn for this.
13143          */
13144
13145         status = cli_list(cli,
13146                         wild_name,
13147                         0,
13148                         smb1_wild_mangle_list_fn,
13149                         &mangled_name);
13150         if (!NT_STATUS_IS_OK(status)) {
13151                 printf("cli_list of %s returned %s\n",
13152                         wild_name,
13153                         nt_errstr(status));
13154                 goto out;
13155         }
13156
13157         if (mangled_name == NULL) {
13158                 goto out;
13159         }
13160
13161         printf("mangled_name = %s\n",
13162                 mangled_name);
13163
13164         /*
13165          * Try a Windows rename with the mangled name.
13166          * This should *NOT* rename the 'foo' name.
13167          */
13168
13169         windows_rename_src = talloc_asprintf(cli_posix,
13170                                         "%s\\%s",
13171                                         dname,
13172                                         mangled_name);
13173
13174         status = cli_rename(cli,
13175                         windows_rename_src,
13176                         windows_rename_dst,
13177                         false);
13178         if (!NT_STATUS_IS_OK(status)) {
13179                 printf("cli_rename of %s -> %s returned %s\n",
13180                         windows_rename_src,
13181                         windows_rename_dst,
13182                         nt_errstr(status));
13183                 goto out;
13184         }
13185
13186         /* Does 'foo' still exist ? */
13187         status = cli_posix_open(cli_posix,
13188                                 fooname,
13189                                 O_RDONLY,
13190                                 0,
13191                                 &fnum);
13192         if (!NT_STATUS_IS_OK(status)) {
13193                 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13194                         fooname,
13195                         nt_errstr(status));
13196                 goto out;
13197         }
13198
13199         status = cli_close(cli_posix, fnum);
13200         if (!NT_STATUS_IS_OK(status)) {
13201                 goto out;
13202         }
13203
13204         correct = true;
13205
13206   out:
13207
13208         TALLOC_FREE(mangled_name);
13209         TALLOC_FREE(windows_rename_src);
13210
13211         if (cli != NULL) {
13212                 torture_deltree(cli, dname);
13213                 torture_close_connection(cli);
13214         }
13215
13216         torture_close_connection(cli_posix);
13217
13218         return correct;
13219 }
13220
13221 /*
13222  * Only testing minimal time strings, as the others
13223  * need (locale-dependent) guessing at what strftime does and
13224  * even may differ in builds.
13225  */
13226 static bool timesubst_test(void)
13227 {
13228         TALLOC_CTX *ctx = NULL;
13229         /* Sa 23. Dez 04:33:20 CET 2017 */
13230         const struct timeval tv = { 1514000000, 123 };
13231         const char* expect_minimal = "20171223_033320";
13232         const char* expect_minus   = "20171223_033320_000123";
13233         char *s;
13234         char *env_tz, *orig_tz = NULL;
13235         bool result = true;
13236
13237         ctx = talloc_new(NULL);
13238
13239         env_tz = getenv("TZ");
13240         if(env_tz) {
13241                 orig_tz = talloc_strdup(ctx, env_tz);
13242         }
13243         setenv("TZ", "UTC", 1);
13244
13245         s = minimal_timeval_string(ctx, &tv, false);
13246
13247         if(!s || strcmp(s, expect_minimal)) {
13248                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13249                        "[%s]\n", s ? s : "<nil>", expect_minimal);
13250                 result = false;
13251         }
13252         TALLOC_FREE(s);
13253         s = minimal_timeval_string(ctx, &tv, true);
13254         if(!s || strcmp(s, expect_minus)) {
13255                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13256                        "[%s]\n", s ? s : "<nil>", expect_minus);
13257                 result = false;
13258         }
13259         TALLOC_FREE(s);
13260
13261         if(orig_tz) {
13262                 setenv("TZ", orig_tz, 1);
13263         }
13264
13265         TALLOC_FREE(ctx);
13266         return result;
13267 }
13268
13269 static bool run_local_substitute(int dummy)
13270 {
13271         bool ok = true;
13272
13273         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13274         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13275         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13276         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13277         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13278         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13279         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13280         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13281         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13282         /* Substitution depends on current time, so better test the underlying
13283            formatting function. At least covers %t. */
13284         ok &= timesubst_test();
13285
13286         /* Different captialization rules in sub_basic... */
13287
13288         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13289                        "blaDOM") == 0);
13290
13291         return ok;
13292 }
13293
13294 static bool run_local_base64(int dummy)
13295 {
13296         int i;
13297         bool ret = true;
13298
13299         for (i=1; i<2000; i++) {
13300                 DATA_BLOB blob1, blob2;
13301                 char *b64;
13302
13303                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13304                 blob1.length = i;
13305                 generate_random_buffer(blob1.data, blob1.length);
13306
13307                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13308                 if (b64 == NULL) {
13309                         d_fprintf(stderr, "base64_encode_data_blob failed "
13310                                   "for %d bytes\n", i);
13311                         ret = false;
13312                 }
13313                 blob2 = base64_decode_data_blob(b64);
13314                 TALLOC_FREE(b64);
13315
13316                 if (data_blob_cmp(&blob1, &blob2)) {
13317                         d_fprintf(stderr, "data_blob_cmp failed for %d "
13318                                   "bytes\n", i);
13319                         ret = false;
13320                 }
13321                 TALLOC_FREE(blob1.data);
13322                 data_blob_free(&blob2);
13323         }
13324         return ret;
13325 }
13326
13327 static void parse_fn(const struct gencache_timeout *t,
13328                      DATA_BLOB blob,
13329                      void *private_data)
13330 {
13331         return;
13332 }
13333
13334 static bool run_local_gencache(int dummy)
13335 {
13336         char *val;
13337         time_t tm;
13338         DATA_BLOB blob;
13339         char v;
13340         struct memcache *mem;
13341         int i;
13342
13343         mem = memcache_init(NULL, 0);
13344         if (mem == NULL) {
13345                 d_printf("%s: memcache_init failed\n", __location__);
13346                 return false;
13347         }
13348         memcache_set_global(mem);
13349
13350         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13351                 d_printf("%s: gencache_set() failed\n", __location__);
13352                 return False;
13353         }
13354
13355         if (!gencache_get("foo", NULL, NULL, NULL)) {
13356                 d_printf("%s: gencache_get() failed\n", __location__);
13357                 return False;
13358         }
13359
13360         for (i=0; i<1000000; i++) {
13361                 gencache_parse("foo", parse_fn, NULL);
13362         }
13363
13364         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13365                 d_printf("%s: gencache_get() failed\n", __location__);
13366                 return False;
13367         }
13368         TALLOC_FREE(val);
13369
13370         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13371                 d_printf("%s: gencache_get() failed\n", __location__);
13372                 return False;
13373         }
13374
13375         if (strcmp(val, "bar") != 0) {
13376                 d_printf("%s: gencache_get() returned %s, expected %s\n",
13377                          __location__, val, "bar");
13378                 TALLOC_FREE(val);
13379                 return False;
13380         }
13381
13382         TALLOC_FREE(val);
13383
13384         if (!gencache_del("foo")) {
13385                 d_printf("%s: gencache_del() failed\n", __location__);
13386                 return False;
13387         }
13388         if (gencache_del("foo")) {
13389                 d_printf("%s: second gencache_del() succeeded\n",
13390                          __location__);
13391                 return False;
13392         }
13393
13394         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13395                 d_printf("%s: gencache_get() on deleted entry "
13396                          "succeeded\n", __location__);
13397                 return False;
13398         }
13399
13400         blob = data_blob_string_const_null("bar");
13401         tm = time(NULL) + 60;
13402
13403         if (!gencache_set_data_blob("foo", blob, tm)) {
13404                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13405                 return False;
13406         }
13407
13408         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13409                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13410                 return False;
13411         }
13412
13413         if (strcmp((const char *)blob.data, "bar") != 0) {
13414                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13415                          __location__, (const char *)blob.data, "bar");
13416                 data_blob_free(&blob);
13417                 return False;
13418         }
13419
13420         data_blob_free(&blob);
13421
13422         if (!gencache_del("foo")) {
13423                 d_printf("%s: gencache_del() failed\n", __location__);
13424                 return False;
13425         }
13426         if (gencache_del("foo")) {
13427                 d_printf("%s: second gencache_del() succeeded\n",
13428                          __location__);
13429                 return False;
13430         }
13431
13432         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13433                 d_printf("%s: gencache_get_data_blob() on deleted entry "
13434                          "succeeded\n", __location__);
13435                 return False;
13436         }
13437
13438         v = 1;
13439         blob.data = (uint8_t *)&v;
13440         blob.length = sizeof(v);
13441
13442         if (!gencache_set_data_blob("blob", blob, tm)) {
13443                 d_printf("%s: gencache_set_data_blob() failed\n",
13444                          __location__);
13445                 return false;
13446         }
13447         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13448                 d_printf("%s: gencache_get succeeded\n", __location__);
13449                 return false;
13450         }
13451
13452         return True;
13453 }
13454
13455 static bool rbt_testflags(struct db_context *db, const char *key,
13456                           const char *value)
13457 {
13458         bool ret = false;
13459         NTSTATUS status;
13460         struct db_record *rec;
13461
13462         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13463         if (rec == NULL) {
13464                 d_fprintf(stderr, "fetch_locked failed\n");
13465                 goto done;
13466         }
13467
13468         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13469         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13470                 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13471                           nt_errstr(status));
13472                 goto done;
13473         }
13474
13475         status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13476                                      TDB_INSERT);
13477         if (!NT_STATUS_IS_OK(status)) {
13478                 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13479                           nt_errstr(status));
13480                 goto done;
13481         }
13482
13483         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13484         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13485                 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13486                           nt_errstr(status));
13487                 goto done;
13488         }
13489
13490         status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13491         if (!NT_STATUS_IS_OK(status)) {
13492                 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13493                           nt_errstr(status));
13494                 goto done;
13495         }
13496
13497         ret = true;
13498 done:
13499         TALLOC_FREE(rec);
13500         return ret;
13501 }
13502
13503 static bool rbt_testval(struct db_context *db, const char *key,
13504                         const char *value)
13505 {
13506         struct db_record *rec;
13507         TDB_DATA data = string_tdb_data(value);
13508         bool ret = false;
13509         NTSTATUS status;
13510         TDB_DATA dbvalue;
13511
13512         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13513         if (rec == NULL) {
13514                 d_fprintf(stderr, "fetch_locked failed\n");
13515                 goto done;
13516         }
13517         status = dbwrap_record_store(rec, data, 0);
13518         if (!NT_STATUS_IS_OK(status)) {
13519                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13520                 goto done;
13521         }
13522         TALLOC_FREE(rec);
13523
13524         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13525         if (rec == NULL) {
13526                 d_fprintf(stderr, "second fetch_locked failed\n");
13527                 goto done;
13528         }
13529
13530         dbvalue = dbwrap_record_get_value(rec);
13531         if ((dbvalue.dsize != data.dsize)
13532             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13533                 d_fprintf(stderr, "Got wrong data back\n");
13534                 goto done;
13535         }
13536
13537         ret = true;
13538  done:
13539         TALLOC_FREE(rec);
13540         return ret;
13541 }
13542
13543 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13544 {
13545         int *count2 = (int *)private_data;
13546         (*count2)++;
13547         return 0;
13548 }
13549
13550 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13551 {
13552         int *count2 = (int *)private_data;
13553         (*count2)++;
13554         dbwrap_record_delete(rec);
13555         return 0;
13556 }
13557
13558 static bool run_local_rbtree(int dummy)
13559 {
13560         struct db_context *db;
13561         bool ret = false;
13562         int i;
13563         NTSTATUS status;
13564         int count = 0;
13565         int count2 = 0;
13566
13567         db = db_open_rbt(NULL);
13568
13569         if (db == NULL) {
13570                 d_fprintf(stderr, "db_open_rbt failed\n");
13571                 return false;
13572         }
13573
13574         if (!rbt_testflags(db, "firstkey", "firstval")) {
13575                 goto done;
13576         }
13577
13578         for (i = 0; i < 999; i++) {
13579                 char key[sizeof("key-9223372036854775807")];
13580                 char value[sizeof("value-9223372036854775807")];
13581
13582                 snprintf(key, sizeof(key), "key%ld", random());
13583                 snprintf(value, sizeof(value) ,"value%ld", random());
13584
13585                 if (!rbt_testval(db, key, value)) {
13586                         goto done;
13587                 }
13588
13589                 snprintf(value, sizeof(value) ,"value%ld", random());
13590
13591                 if (!rbt_testval(db, key, value)) {
13592                         goto done;
13593                 }
13594         }
13595
13596         ret = true;
13597         count = 0; count2 = 0;
13598         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13599                                       &count2, &count);
13600         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13601         if ((count != count2) || (count != 1000)) {
13602                 ret = false;
13603         }
13604         count = 0; count2 = 0;
13605         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13606                                  &count2, &count);
13607         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13608         if ((count != count2) || (count != 1000)) {
13609                 ret = false;
13610         }
13611         count = 0; count2 = 0;
13612         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13613                                       &count2, &count);
13614         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13615         if ((count != count2) || (count != 0)) {
13616                 ret = false;
13617         }
13618
13619  done:
13620         TALLOC_FREE(db);
13621         return ret;
13622 }
13623
13624
13625 /*
13626   local test for character set functions
13627
13628   This is a very simple test for the functionality in convert_string_error()
13629  */
13630 static bool run_local_convert_string(int dummy)
13631 {
13632         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13633         const char *test_strings[2] = { "March", "M\303\244rz" };
13634         char dst[7];
13635         int i;
13636
13637         for (i=0; i<2; i++) {
13638                 const char *str = test_strings[i];
13639                 int len = strlen(str);
13640                 size_t converted_size;
13641                 bool ret;
13642
13643                 memset(dst, 'X', sizeof(dst));
13644
13645                 /* first try with real source length */
13646                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13647                                            str, len,
13648                                            dst, sizeof(dst),
13649                                            &converted_size);
13650                 if (ret != true) {
13651                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13652                         goto failed;
13653                 }
13654
13655                 if (converted_size != len) {
13656                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13657                                   str, len, (int)converted_size);
13658                         goto failed;
13659                 }
13660
13661                 if (strncmp(str, dst, converted_size) != 0) {
13662                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13663                         goto failed;
13664                 }
13665
13666                 if (strlen(str) != converted_size) {
13667                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13668                                   (int)strlen(str), (int)converted_size);
13669                         goto failed;
13670                 }
13671
13672                 if (dst[converted_size] != 'X') {
13673                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13674                         goto failed;
13675                 }
13676
13677                 /* now with srclen==-1, this causes the nul to be
13678                  * converted too */
13679                 ret = convert_string_error(CH_UNIX, CH_UTF8,
13680                                            str, -1,
13681                                            dst, sizeof(dst),
13682                                            &converted_size);
13683                 if (ret != true) {
13684                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13685                         goto failed;
13686                 }
13687
13688                 if (converted_size != len+1) {
13689                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13690                                   str, len, (int)converted_size);
13691                         goto failed;
13692                 }
13693
13694                 if (strncmp(str, dst, converted_size) != 0) {
13695                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13696                         goto failed;
13697                 }
13698
13699                 if (len+1 != converted_size) {
13700                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13701                                   len+1, (int)converted_size);
13702                         goto failed;
13703                 }
13704
13705                 if (dst[converted_size] != 'X') {
13706                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13707                         goto failed;
13708                 }
13709
13710         }
13711
13712
13713         TALLOC_FREE(tmp_ctx);
13714         return true;
13715 failed:
13716         TALLOC_FREE(tmp_ctx);
13717         return false;
13718 }
13719
13720 static bool run_local_string_to_sid(int dummy) {
13721         struct dom_sid sid;
13722
13723         if (string_to_sid(&sid, "S--1-5-32-545")) {
13724                 printf("allowing S--1-5-32-545\n");
13725                 return false;
13726         }
13727         if (string_to_sid(&sid, "S-1-5-32-+545")) {
13728                 printf("allowing S-1-5-32-+545\n");
13729                 return false;
13730         }
13731         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")) {
13732                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13733                 return false;
13734         }
13735         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13736                 printf("allowing S-1-5-32-545-abc\n");
13737                 return false;
13738         }
13739         if (string_to_sid(&sid, "S-300-5-32-545")) {
13740                 printf("allowing S-300-5-32-545\n");
13741                 return false;
13742         }
13743         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13744                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13745                 return false;
13746         }
13747         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13748                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13749                 return false;
13750         }
13751         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13752                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13753                 return false;
13754         }
13755         if (!string_to_sid(&sid, "S-1-5-32-545")) {
13756                 printf("could not parse S-1-5-32-545\n");
13757                 return false;
13758         }
13759         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13760                 struct dom_sid_buf buf;
13761                 printf("mis-parsed S-1-5-32-545 as %s\n",
13762                        dom_sid_str_buf(&sid, &buf));
13763                 return false;
13764         }
13765         return true;
13766 }
13767
13768 static bool sid_to_string_test(const char *expected) {
13769         char *str;
13770         bool res = true;
13771         struct dom_sid sid;
13772
13773         if (!string_to_sid(&sid, expected)) {
13774                 printf("could not parse %s\n", expected);
13775                 return false;
13776         }
13777
13778         str = dom_sid_string(NULL, &sid);
13779         if (strcmp(str, expected)) {
13780                 printf("Comparison failed (%s != %s)\n", str, expected);
13781                 res = false;
13782         }
13783         TALLOC_FREE(str);
13784         return res;
13785 }
13786
13787 static bool run_local_sid_to_string(int dummy) {
13788         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13789                 return false;
13790         if (!sid_to_string_test("S-1-545"))
13791                 return false;
13792         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13793                 return false;
13794         return true;
13795 }
13796
13797 static bool run_local_binary_to_sid(int dummy) {
13798         ssize_t ret;
13799         struct dom_sid *sid = talloc(NULL, struct dom_sid);
13800         static const uint8_t good_binary_sid[] = {
13801                 0x1, /* revision number */
13802                 15, /* num auths */
13803                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13804                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13805                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13806                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13807                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13808                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13809                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13810                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13811                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13812                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13813                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13814                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13815                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13816                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13817                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13818                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13819         };
13820
13821         static const uint8_t long_binary_sid[] = {
13822                 0x1, /* revision number */
13823                 15, /* num auths */
13824                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13825                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13826                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13827                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13828                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13829                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13830                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13831                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13832                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13833                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13834                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13835                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13836                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13837                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13838                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13839                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13840                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13841                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13842                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13843         };
13844
13845         static const uint8_t long_binary_sid2[] = {
13846                 0x1, /* revision number */
13847                 32, /* 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                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13865                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13866                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13867                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13868                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13869                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13870                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13871                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13872                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13873                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13874                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13875                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13876                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13877                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13878                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13879                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13880                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13881         };
13882
13883         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13884         if (ret == -1) {
13885                 return false;
13886         }
13887         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13888         if (ret != -1) {
13889                 return false;
13890         }
13891         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13892         if (ret != -1) {
13893                 return false;
13894         }
13895         return true;
13896 }
13897
13898 /* Split a path name into filename and stream name components. Canonicalise
13899  * such that an implicit $DATA token is always explicit.
13900  *
13901  * The "specification" of this function can be found in the
13902  * run_local_stream_name() function in torture.c, I've tried those
13903  * combinations against a W2k3 server.
13904  */
13905
13906 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13907                                        char **pbase, char **pstream)
13908 {
13909         char *base = NULL;
13910         char *stream = NULL;
13911         char *sname; /* stream name */
13912         const char *stype; /* stream type */
13913
13914         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13915
13916         sname = strchr_m(fname, ':');
13917
13918         if (sname == NULL) {
13919                 if (pbase != NULL) {
13920                         base = talloc_strdup(mem_ctx, fname);
13921                         NT_STATUS_HAVE_NO_MEMORY(base);
13922                 }
13923                 goto done;
13924         }
13925
13926         if (pbase != NULL) {
13927                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13928                 NT_STATUS_HAVE_NO_MEMORY(base);
13929         }
13930
13931         sname += 1;
13932
13933         stype = strchr_m(sname, ':');
13934
13935         if (stype == NULL) {
13936                 sname = talloc_strdup(mem_ctx, sname);
13937                 stype = "$DATA";
13938         }
13939         else {
13940                 if (strcasecmp_m(stype, ":$DATA") != 0) {
13941                         /*
13942                          * If there is an explicit stream type, so far we only
13943                          * allow $DATA. Is there anything else allowed? -- vl
13944                          */
13945                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13946                         TALLOC_FREE(base);
13947                         return NT_STATUS_OBJECT_NAME_INVALID;
13948                 }
13949                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13950                 stype += 1;
13951         }
13952
13953         if (sname == NULL) {
13954                 TALLOC_FREE(base);
13955                 return NT_STATUS_NO_MEMORY;
13956         }
13957
13958         if (sname[0] == '\0') {
13959                 /*
13960                  * no stream name, so no stream
13961                  */
13962                 goto done;
13963         }
13964
13965         if (pstream != NULL) {
13966                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13967                 if (stream == NULL) {
13968                         TALLOC_FREE(sname);
13969                         TALLOC_FREE(base);
13970                         return NT_STATUS_NO_MEMORY;
13971                 }
13972                 /*
13973                  * upper-case the type field
13974                  */
13975                 (void)strupper_m(strchr_m(stream, ':')+1);
13976         }
13977
13978  done:
13979         if (pbase != NULL) {
13980                 *pbase = base;
13981         }
13982         if (pstream != NULL) {
13983                 *pstream = stream;
13984         }
13985         return NT_STATUS_OK;
13986 }
13987
13988 static bool test_stream_name(const char *fname, const char *expected_base,
13989                              const char *expected_stream,
13990                              NTSTATUS expected_status)
13991 {
13992         NTSTATUS status;
13993         char *base = NULL;
13994         char *stream = NULL;
13995
13996         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13997         if (!NT_STATUS_EQUAL(status, expected_status)) {
13998                 goto error;
13999         }
14000
14001         if (!NT_STATUS_IS_OK(status)) {
14002                 return true;
14003         }
14004
14005         if (base == NULL) goto error;
14006
14007         if (strcmp(expected_base, base) != 0) goto error;
14008
14009         if ((expected_stream != NULL) && (stream == NULL)) goto error;
14010         if ((expected_stream == NULL) && (stream != NULL)) goto error;
14011
14012         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14013                 goto error;
14014
14015         TALLOC_FREE(base);
14016         TALLOC_FREE(stream);
14017         return true;
14018
14019  error:
14020         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14021                   fname, expected_base ? expected_base : "<NULL>",
14022                   expected_stream ? expected_stream : "<NULL>",
14023                   nt_errstr(expected_status));
14024         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14025                   base ? base : "<NULL>", stream ? stream : "<NULL>",
14026                   nt_errstr(status));
14027         TALLOC_FREE(base);
14028         TALLOC_FREE(stream);
14029         return false;
14030 }
14031
14032 static bool run_local_stream_name(int dummy)
14033 {
14034         bool ret = true;
14035
14036         ret &= test_stream_name(
14037                 "bla", "bla", NULL, NT_STATUS_OK);
14038         ret &= test_stream_name(
14039                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14040         ret &= test_stream_name(
14041                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14042         ret &= test_stream_name(
14043                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14044         ret &= test_stream_name(
14045                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14046         ret &= test_stream_name(
14047                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14048         ret &= test_stream_name(
14049                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14050         ret &= test_stream_name(
14051                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14052
14053         return ret;
14054 }
14055
14056 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14057 {
14058         if (a.length != b.length) {
14059                 printf("a.length=%d != b.length=%d\n",
14060                        (int)a.length, (int)b.length);
14061                 return false;
14062         }
14063         if (memcmp(a.data, b.data, a.length) != 0) {
14064                 printf("a.data and b.data differ\n");
14065                 return false;
14066         }
14067         return true;
14068 }
14069
14070 static bool run_local_memcache(int dummy)
14071 {
14072         struct memcache *cache;
14073         DATA_BLOB k1, k2, k3, k4, k5;
14074         DATA_BLOB d1, d3;
14075         DATA_BLOB v1, v3;
14076
14077         TALLOC_CTX *mem_ctx;
14078         char *ptr1 = NULL;
14079         char *ptr2 = NULL;
14080         char *ptr3 = NULL;
14081
14082         char *str1, *str2;
14083         size_t size1, size2;
14084         bool ret = false;
14085
14086         mem_ctx = talloc_init("foo");
14087         if (mem_ctx == NULL) {
14088                 return false;
14089         }
14090
14091         /* STAT_CACHE TESTS */
14092
14093         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14094
14095         if (cache == NULL) {
14096                 printf("memcache_init failed\n");
14097                 return false;
14098         }
14099
14100         d1 = data_blob_const("d1", 2);
14101         d3 = data_blob_const("d3", 2);
14102
14103         k1 = data_blob_const("d1", 2);
14104         k2 = data_blob_const("d2", 2);
14105         k3 = data_blob_const("d3", 2);
14106         k4 = data_blob_const("d4", 2);
14107         k5 = data_blob_const("d5", 2);
14108
14109         memcache_add(cache, STAT_CACHE, k1, d1);
14110
14111         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14112                 printf("could not find k1\n");
14113                 return false;
14114         }
14115         if (!data_blob_equal(d1, v1)) {
14116                 return false;
14117         }
14118
14119         memcache_add(cache, STAT_CACHE, k1, d3);
14120
14121         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14122                 printf("could not find replaced k1\n");
14123                 return false;
14124         }
14125         if (!data_blob_equal(d3, v3)) {
14126                 return false;
14127         }
14128
14129         TALLOC_FREE(cache);
14130
14131         /* GETWD_CACHE TESTS */
14132         str1 = talloc_strdup(mem_ctx, "string1");
14133         if (str1 == NULL) {
14134                 return false;
14135         }
14136         ptr2 = str1; /* Keep an alias for comparison. */
14137
14138         str2 = talloc_strdup(mem_ctx, "string2");
14139         if (str2 == NULL) {
14140                 return false;
14141         }
14142
14143         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14144         if (cache == NULL) {
14145                 printf("memcache_init failed\n");
14146                 return false;
14147         }
14148
14149         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14150         /* str1 == NULL now. */
14151         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14152         if (ptr1 == NULL) {
14153                 printf("could not find k2\n");
14154                 return false;
14155         }
14156         if (ptr1 != ptr2) {
14157                 printf("fetch of k2 got wrong string\n");
14158                 return false;
14159         }
14160
14161         /* Add a blob to ensure k2 gets purged. */
14162         d3 = data_blob_talloc_zero(mem_ctx, 180);
14163         memcache_add(cache, STAT_CACHE, k3, d3);
14164
14165         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14166         if (ptr2 != NULL) {
14167                 printf("Did find k2, should have been purged\n");
14168                 return false;
14169         }
14170
14171         /*
14172          * Test that talloc size also is accounted in memcache and
14173          * causes purge of other object.
14174          */
14175
14176         str1 = talloc_zero_size(mem_ctx, 100);
14177         str2 = talloc_zero_size(mem_ctx, 100);
14178
14179         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14180         memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14181
14182         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14183         if (ptr3 != NULL) {
14184                 printf("Did find k4, should have been purged\n");
14185                 return false;
14186         }
14187
14188         /*
14189          * Test that adding a duplicate non-talloced
14190          * key/value on top of a talloced key/value takes account
14191          * of the talloc_freed value size.
14192          */
14193         TALLOC_FREE(cache);
14194         TALLOC_FREE(mem_ctx);
14195
14196         mem_ctx = talloc_init("key_replace");
14197         if (mem_ctx == NULL) {
14198                 return false;
14199         }
14200
14201         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14202         if (cache == NULL) {
14203                 return false;
14204         }
14205
14206         /*
14207          * Add a 100 byte talloced string. This will
14208          * store a (4 or 8 byte) pointer and record the
14209          * total talloced size.
14210          */
14211         str1 = talloc_zero_size(mem_ctx, 100);
14212         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14213         /*
14214          * Now overwrite with a small talloced
14215          * value. This should fit in the existing size
14216          * and the total talloced size should be removed
14217          * from the cache size.
14218          */
14219         str1 = talloc_zero_size(mem_ctx, 2);
14220         memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14221         /*
14222          * Now store a 20 byte string. If the
14223          * total talloced size wasn't accounted for
14224          * and removed in the overwrite, then this
14225          * will evict k4.
14226          */
14227         str2 = talloc_zero_size(mem_ctx, 20);
14228         memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14229
14230         ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14231         if (ptr3 == NULL) {
14232                 printf("Did not find k4, should not have been purged\n");
14233                 return false;
14234         }
14235
14236         TALLOC_FREE(cache);
14237         TALLOC_FREE(mem_ctx);
14238
14239         mem_ctx = talloc_init("foo");
14240         if (mem_ctx == NULL) {
14241                 return false;
14242         }
14243
14244         cache = memcache_init(NULL, 0);
14245         if (cache == NULL) {
14246                 return false;
14247         }
14248
14249         str1 = talloc_strdup(mem_ctx, "string1");
14250         if (str1 == NULL) {
14251                 return false;
14252         }
14253         str2 = talloc_strdup(mem_ctx, "string2");
14254         if (str2 == NULL) {
14255                 return false;
14256         }
14257         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14258                             data_blob_string_const("torture"), &str1);
14259         size1 = talloc_total_size(cache);
14260
14261         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14262                             data_blob_string_const("torture"), &str2);
14263         size2 = talloc_total_size(cache);
14264
14265         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14266
14267         if (size2 > size1) {
14268                 printf("memcache leaks memory!\n");
14269                 goto fail;
14270         }
14271
14272         ret = true;
14273  fail:
14274         TALLOC_FREE(cache);
14275         return ret;
14276 }
14277
14278 static void wbclient_done(struct tevent_req *req)
14279 {
14280         wbcErr wbc_err;
14281         struct winbindd_response *wb_resp;
14282         int *i = (int *)tevent_req_callback_data_void(req);
14283
14284         wbc_err = wb_trans_recv(req, req, &wb_resp);
14285         TALLOC_FREE(req);
14286         *i += 1;
14287         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14288 }
14289
14290 static bool run_wbclient_multi_ping(int dummy)
14291 {
14292         struct tevent_context *ev;
14293         struct wb_context **wb_ctx;
14294         struct winbindd_request wb_req;
14295         bool result = false;
14296         int i, j;
14297
14298         BlockSignals(True, SIGPIPE);
14299
14300         ev = tevent_context_init(talloc_tos());
14301         if (ev == NULL) {
14302                 goto fail;
14303         }
14304
14305         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14306         if (wb_ctx == NULL) {
14307                 goto fail;
14308         }
14309
14310         ZERO_STRUCT(wb_req);
14311         wb_req.cmd = WINBINDD_PING;
14312
14313         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14314
14315         for (i=0; i<torture_nprocs; i++) {
14316                 wb_ctx[i] = wb_context_init(ev, NULL);
14317                 if (wb_ctx[i] == NULL) {
14318                         goto fail;
14319                 }
14320                 for (j=0; j<torture_numops; j++) {
14321                         struct tevent_req *req;
14322                         req = wb_trans_send(ev, ev, wb_ctx[i],
14323                                             (j % 2) == 0, &wb_req);
14324                         if (req == NULL) {
14325                                 goto fail;
14326                         }
14327                         tevent_req_set_callback(req, wbclient_done, &i);
14328                 }
14329         }
14330
14331         i = 0;
14332
14333         while (i < torture_nprocs * torture_numops) {
14334                 tevent_loop_once(ev);
14335         }
14336
14337         result = true;
14338  fail:
14339         TALLOC_FREE(ev);
14340         return result;
14341 }
14342
14343 static bool dbtrans_inc(struct db_context *db)
14344 {
14345         struct db_record *rec;
14346         uint32_t val;
14347         bool ret = false;
14348         NTSTATUS status;
14349         TDB_DATA value;
14350
14351         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14352         if (rec == NULL) {
14353                 printf(__location__ "fetch_lock failed\n");
14354                 return false;
14355         }
14356
14357         value = dbwrap_record_get_value(rec);
14358
14359         if (value.dsize != sizeof(uint32_t)) {
14360                 printf(__location__ "value.dsize = %d\n",
14361                        (int)value.dsize);
14362                 goto fail;
14363         }
14364
14365         memcpy(&val, value.dptr, sizeof(val));
14366         val += 1;
14367
14368         status = dbwrap_record_store(
14369                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14370         if (!NT_STATUS_IS_OK(status)) {
14371                 printf(__location__ "store failed: %s\n",
14372                        nt_errstr(status));
14373                 goto fail;
14374         }
14375
14376         ret = true;
14377 fail:
14378         TALLOC_FREE(rec);
14379         return ret;
14380 }
14381
14382 static bool run_local_dbtrans(int dummy)
14383 {
14384         struct db_context *db;
14385         struct db_record *rec;
14386         NTSTATUS status;
14387         uint32_t initial;
14388         int res;
14389         TDB_DATA value;
14390
14391         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14392                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14393                      DBWRAP_FLAG_NONE);
14394         if (db == NULL) {
14395                 printf("Could not open transtest.db\n");
14396                 return false;
14397         }
14398
14399         res = dbwrap_transaction_start(db);
14400         if (res != 0) {
14401                 printf(__location__ "transaction_start failed\n");
14402                 return false;
14403         }
14404
14405         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14406         if (rec == NULL) {
14407                 printf(__location__ "fetch_lock failed\n");
14408                 return false;
14409         }
14410
14411         value = dbwrap_record_get_value(rec);
14412
14413         if (value.dptr == NULL) {
14414                 initial = 0;
14415                 status = dbwrap_record_store(
14416                         rec, make_tdb_data((uint8_t *)&initial,
14417                                            sizeof(initial)),
14418                         0);
14419                 if (!NT_STATUS_IS_OK(status)) {
14420                         printf(__location__ "store returned %s\n",
14421                                nt_errstr(status));
14422                         return false;
14423                 }
14424         }
14425
14426         TALLOC_FREE(rec);
14427
14428         res = dbwrap_transaction_commit(db);
14429         if (res != 0) {
14430                 printf(__location__ "transaction_commit failed\n");
14431                 return false;
14432         }
14433
14434         while (true) {
14435                 uint32_t val, val2;
14436                 int i;
14437
14438                 res = dbwrap_transaction_start(db);
14439                 if (res != 0) {
14440                         printf(__location__ "transaction_start failed\n");
14441                         break;
14442                 }
14443
14444                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14445                 if (!NT_STATUS_IS_OK(status)) {
14446                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14447                                nt_errstr(status));
14448                         break;
14449                 }
14450
14451                 for (i=0; i<10; i++) {
14452                         if (!dbtrans_inc(db)) {
14453                                 return false;
14454                         }
14455                 }
14456
14457                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14458                 if (!NT_STATUS_IS_OK(status)) {
14459                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14460                                nt_errstr(status));
14461                         break;
14462                 }
14463
14464                 if (val2 != val + 10) {
14465                         printf(__location__ "val=%d, val2=%d\n",
14466                                (int)val, (int)val2);
14467                         break;
14468                 }
14469
14470                 printf("val2=%d\r", val2);
14471
14472                 res = dbwrap_transaction_commit(db);
14473                 if (res != 0) {
14474                         printf(__location__ "transaction_commit failed\n");
14475                         break;
14476                 }
14477         }
14478
14479         TALLOC_FREE(db);
14480         return true;
14481 }
14482
14483 /*
14484  * Just a dummy test to be run under a debugger. There's no real way
14485  * to inspect the tevent_poll specific function from outside of
14486  * tevent_poll.c.
14487  */
14488
14489 static bool run_local_tevent_poll(int dummy)
14490 {
14491         struct tevent_context *ev;
14492         struct tevent_fd *fd1, *fd2;
14493         bool result = false;
14494
14495         ev = tevent_context_init_byname(NULL, "poll");
14496         if (ev == NULL) {
14497                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14498                 goto fail;
14499         }
14500
14501         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14502         if (fd1 == NULL) {
14503                 d_fprintf(stderr, "tevent_add_fd failed\n");
14504                 goto fail;
14505         }
14506         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14507         if (fd2 == NULL) {
14508                 d_fprintf(stderr, "tevent_add_fd failed\n");
14509                 goto fail;
14510         }
14511         TALLOC_FREE(fd2);
14512
14513         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14514         if (fd2 == NULL) {
14515                 d_fprintf(stderr, "tevent_add_fd failed\n");
14516                 goto fail;
14517         }
14518
14519         result = true;
14520 fail:
14521         TALLOC_FREE(ev);
14522         return result;
14523 }
14524
14525 static bool run_local_hex_encode_buf(int dummy)
14526 {
14527         char buf[17];
14528         uint8_t src[8];
14529         size_t i;
14530
14531         for (i=0; i<sizeof(src); i++) {
14532                 src[i] = i;
14533         }
14534         hex_encode_buf(buf, src, sizeof(src));
14535         if (strcmp(buf, "0001020304050607") != 0) {
14536                 return false;
14537         }
14538         hex_encode_buf(buf, NULL, 0);
14539         if (buf[0] != '\0') {
14540                 return false;
14541         }
14542         return true;
14543 }
14544
14545 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14546         "0.0.0.0",
14547         "::0",
14548         "1.2.3.1",
14549         "0.0.0.0",
14550         "0.0.0.0",
14551         "1.2.3.2",
14552         "1.2.3.3",
14553         "1.2.3.4",
14554         "1.2.3.5",
14555         "::0",
14556         "1.2.3.6",
14557         "1.2.3.7",
14558         "::0",
14559         "::0",
14560         "::0",
14561         "1.2.3.8",
14562         "1.2.3.9",
14563         "1.2.3.10",
14564         "1.2.3.11",
14565         "1.2.3.12",
14566         "1.2.3.13",
14567         "1001:1111:1111:1000:0:1111:1111:1111",
14568         "1.2.3.1",
14569         "1.2.3.2",
14570         "1.2.3.3",
14571         "1.2.3.12",
14572         "::0",
14573         "::0"
14574 };
14575
14576 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14577         "1.2.3.1",
14578         "1.2.3.2",
14579         "1.2.3.3",
14580         "1.2.3.4",
14581         "1.2.3.5",
14582         "1.2.3.6",
14583         "1.2.3.7",
14584         "1.2.3.8",
14585         "1.2.3.9",
14586         "1.2.3.10",
14587         "1.2.3.11",
14588         "1.2.3.12",
14589         "1.2.3.13",
14590         "1001:1111:1111:1000:0:1111:1111:1111"
14591 };
14592
14593 static bool run_local_remove_duplicate_addrs2(int dummy)
14594 {
14595         struct samba_sockaddr test_vector[28];
14596         size_t count, i;
14597
14598         /* Construct the sockaddr_storage test vector. */
14599         for (i = 0; i < 28; i++) {
14600                 struct addrinfo hints;
14601                 struct addrinfo *res = NULL;
14602                 int ret;
14603
14604                 memset(&hints, '\0', sizeof(hints));
14605                 hints.ai_flags = AI_NUMERICHOST;
14606                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14607                                 NULL,
14608                                 &hints,
14609                                 &res);
14610                 if (ret) {
14611                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
14612                                 remove_duplicate_addrs2_test_strings_vector[i]);
14613                         return false;
14614                 }
14615                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14616                 memcpy(&test_vector[i].u.ss,
14617                         res->ai_addr,
14618                         res->ai_addrlen);
14619                 freeaddrinfo(res);
14620         }
14621
14622         count = remove_duplicate_addrs2(test_vector, i);
14623
14624         if (count != 14) {
14625                 fprintf(stderr, "count wrong (%zu) should be 14\n",
14626                         count);
14627                 return false;
14628         }
14629
14630         for (i = 0; i < count; i++) {
14631                 char addr[INET6_ADDRSTRLEN];
14632
14633                 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14634
14635                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14636                         fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14637                                 i,
14638                                 addr,
14639                                 remove_duplicate_addrs2_test_strings_result[i]);
14640                         return false;
14641                 }
14642         }
14643
14644         printf("run_local_remove_duplicate_addrs2: success\n");
14645         return true;
14646 }
14647
14648 static bool run_local_tdb_opener(int dummy)
14649 {
14650         TDB_CONTEXT *t;
14651         unsigned v = 0;
14652
14653         while (1) {
14654                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14655                              O_RDWR|O_CREAT, 0755);
14656                 if (t == NULL) {
14657                         perror("tdb_open failed");
14658                         return false;
14659                 }
14660                 tdb_close(t);
14661
14662                 v += 1;
14663                 printf("\r%u", v);
14664         }
14665         return true;
14666 }
14667
14668 static bool run_local_tdb_writer(int dummy)
14669 {
14670         TDB_CONTEXT *t;
14671         unsigned v = 0;
14672         TDB_DATA val;
14673
14674         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14675         if (t == 0) {
14676                 perror("tdb_open failed");
14677                 return 1;
14678         }
14679
14680         val.dptr = (uint8_t *)&v;
14681         val.dsize = sizeof(v);
14682
14683         while (1) {
14684                 TDB_DATA data;
14685                 int ret;
14686
14687                 ret = tdb_store(t, val, val, 0);
14688                 if (ret != 0) {
14689                         printf("%s\n", tdb_errorstr(t));
14690                 }
14691                 v += 1;
14692                 printf("\r%u", v);
14693
14694                 data = tdb_fetch(t, val);
14695                 if (data.dptr != NULL) {
14696                         SAFE_FREE(data.dptr);
14697                 }
14698         }
14699         return true;
14700 }
14701
14702 static bool run_local_canonicalize_path(int dummy)
14703 {
14704         const char *src[] = {
14705                         "/foo/..",
14706                         "/..",
14707                         "/foo/bar/../baz",
14708                         "/foo/././",
14709                         "/../foo",
14710                         ".././././",
14711                         ".././././../../../boo",
14712                         "./..",
14713                         "/",
14714                         "/../../",
14715                         "/foo/../",
14716                         "/./././",
14717                         "/./././.",
14718                         "/.../././.",
14719                         "/./././.foo",
14720                         "/./././.foo.",
14721                         "/./././foo.",
14722                         "/foo/bar/..",
14723                         "/foo/bar/../baz/",
14724                         "////////////////",
14725                         "/////////./././././.",
14726                         "/./.././../.boo/../baz",
14727                         "/a/component/path",
14728                         "/a/component/path/",
14729                         "/a/component/path/..",
14730                         "/a/component/../path/",
14731                         "///a/./././///component/../////path/",
14732                         NULL
14733                         };
14734         const char *dst[] = {
14735                         "/",
14736                         "/",
14737                         "/foo/baz",
14738                         "/foo",
14739                         "/foo",
14740                         "/",
14741                         "/boo",
14742                         "/",
14743                         "/",
14744                         "/",
14745                         "/",
14746                         "/",
14747                         "/",
14748                         "/...",
14749                         "/.foo",
14750                         "/.foo.",
14751                         "/foo.",
14752                         "/foo",
14753                         "/foo/baz",
14754                         "/",
14755                         "/",
14756                         "/baz",
14757                         "/a/component/path",
14758                         "/a/component/path",
14759                         "/a/component",
14760                         "/a/path",
14761                         "/a/path",
14762                         NULL
14763                         };
14764         unsigned int i;
14765
14766         for (i = 0; src[i] != NULL; i++) {
14767                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14768                 if (d == NULL) {
14769                         perror("talloc fail\n");
14770                         return false;
14771                 }
14772                 if (strcmp(d, dst[i]) != 0) {
14773                         d_fprintf(stderr,
14774                                 "canonicalize mismatch %s -> %s != %s",
14775                                 src[i], d, dst[i]);
14776                         return false;
14777                 }
14778                 talloc_free(d);
14779         }
14780         return true;
14781 }
14782 struct session_setup_nt1_truncated_state {
14783         uint16_t vwv[13];
14784         uint8_t bytes[20];
14785 };
14786
14787 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14788
14789 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14790                 TALLOC_CTX *mem_ctx,
14791                 struct tevent_context *ev,
14792                 struct smbXcli_conn *conn)
14793 {
14794         uint16_t *vwv = NULL;
14795         uint8_t *bytes = NULL;
14796         const char *pass = "12345678";
14797         const char *uname = "z";
14798         struct session_setup_nt1_truncated_state *state = NULL;
14799         struct tevent_req *req = NULL;
14800         struct tevent_req *subreq = NULL;
14801
14802         req = tevent_req_create(mem_ctx,
14803                                 &state,
14804                                 struct session_setup_nt1_truncated_state);
14805         if (req == NULL) {
14806                 return NULL;
14807         }
14808         vwv = &state->vwv[0];
14809         bytes = &state->bytes[0];
14810
14811         SCVAL(vwv+0,  0, 0xff);
14812         SCVAL(vwv+0,  1, 0);
14813         SSVAL(vwv+1,  0, 0);
14814         SSVAL(vwv+2,  0, 8192);
14815         SSVAL(vwv+3,  0, 2);
14816         SSVAL(vwv+4,  0, 1);
14817         SIVAL(vwv+5,  0, 0);
14818         SSVAL(vwv+7,  0, strlen(pass)); /* OEMPasswordLen */
14819         SSVAL(vwv+8,  0, 0); /* UnicodePasswordLen */
14820         SSVAL(vwv+9,  0, 0); /* reserved */
14821         SSVAL(vwv+10, 0, 0); /* reserved */
14822         SIVAL(vwv+11, 0, CAP_STATUS32);
14823
14824         memcpy(bytes, pass, strlen(pass));
14825         bytes += strlen(pass);
14826         memcpy(bytes, uname, strlen(uname)+1);
14827
14828         subreq = smb1cli_req_send(state, ev, conn,
14829                                   SMBsesssetupX,
14830                                   0, /*  additional_flags */
14831                                   0, /*  clear_flags */
14832                                   0, /*  additional_flags2 */
14833                                   0, /*  clear_flags2 */
14834                                   10000, /* timeout_msec */
14835                                   getpid(),
14836                                   NULL, /* tcon */
14837                                   NULL, /* session */
14838                                   13, /* wct */
14839                                   state->vwv,
14840                                   strlen(pass), /* Truncate length at password. */
14841                                   state->bytes);
14842         if (tevent_req_nomem(subreq, req)) {
14843                 return tevent_req_post(req, ev);
14844         }
14845         tevent_req_set_callback(subreq,
14846                                 smb1_session_setup_nt1_truncated_done,
14847                                 req);
14848         return req;
14849 }
14850
14851 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14852 {
14853         struct tevent_req *req =
14854                 tevent_req_callback_data(subreq,
14855                 struct tevent_req);
14856         struct session_setup_nt1_truncated_state *state =
14857                 tevent_req_data(req,
14858                 struct session_setup_nt1_truncated_state);
14859         NTSTATUS status;
14860         struct smb1cli_req_expected_response expected[] = {
14861         {
14862                 .status = NT_STATUS_OK,
14863                 .wct    = 3,
14864         },
14865         };
14866
14867         status = smb1cli_req_recv(subreq, state,
14868                                   NULL,
14869                                   NULL,
14870                                   NULL,
14871                                   NULL,
14872                                   NULL, /* pvwv_offset */
14873                                   NULL,
14874                                   NULL,
14875                                   NULL, /* pbytes_offset */
14876                                   NULL,
14877                                   expected, ARRAY_SIZE(expected));
14878         TALLOC_FREE(subreq);
14879         if (tevent_req_nterror(req, status)) {
14880                 return;
14881         }
14882         tevent_req_done(req);
14883 }
14884
14885 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14886 {
14887         return tevent_req_simple_recv_ntstatus(req);
14888 }
14889
14890 static bool run_smb1_truncated_sesssetup(int dummy)
14891 {
14892         struct tevent_context *ev;
14893         struct tevent_req *req;
14894         struct smbXcli_conn *conn;
14895         struct sockaddr_storage ss;
14896         NTSTATUS status;
14897         int fd;
14898         bool ok;
14899
14900         printf("Starting send truncated SMB1 sesssetup.\n");
14901
14902         ok = resolve_name(host, &ss, 0x20, true);
14903         if (!ok) {
14904                 d_fprintf(stderr, "Could not resolve name %s\n", host);
14905                 return false;
14906         }
14907
14908         status = open_socket_out(&ss, 445, 10000, &fd);
14909         if (!NT_STATUS_IS_OK(status)) {
14910                 d_fprintf(stderr, "open_socket_out failed: %s\n",
14911                           nt_errstr(status));
14912                 return false;
14913         }
14914
14915         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14916                                    NULL, 0, NULL);
14917         if (conn == NULL) {
14918                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14919                 return false;
14920         }
14921
14922         status = smbXcli_negprot(conn,
14923                                  0,
14924                                  PROTOCOL_NT1,
14925                                  PROTOCOL_NT1,
14926                                  NULL,
14927                                  NULL,
14928                                  NULL);
14929         if (!NT_STATUS_IS_OK(status)) {
14930                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14931                 return false;
14932         }
14933
14934         ev = samba_tevent_context_init(talloc_tos());
14935         if (ev == NULL) {
14936                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14937                 return false;
14938         }
14939
14940         req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14941         if (req == NULL) {
14942                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14943                 return false;
14944         }
14945
14946         ok = tevent_req_poll_ntstatus(req, ev, &status);
14947         if (!ok) {
14948                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14949                         nt_errstr(status));
14950                 return false;
14951         }
14952
14953         status = smb1_session_setup_nt1_truncated_recv(req);
14954         if (!NT_STATUS_IS_OK(status)) {
14955                 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14956                           "%s, expected NT_STATUS_OK\n",
14957                           nt_errstr(status));
14958                 return false;
14959         }
14960
14961         TALLOC_FREE(conn);
14962         return true;
14963 }
14964
14965 struct smb1_negotiate_exit_state {
14966         int dummy;
14967 };
14968
14969 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14970
14971 static struct tevent_req *smb1_negotiate_exit_send(
14972                 TALLOC_CTX *mem_ctx,
14973                 struct tevent_context *ev,
14974                 struct smbXcli_conn *conn)
14975 {
14976         struct smb1_negotiate_exit_state *state = NULL;
14977         struct tevent_req *req = NULL;
14978         struct tevent_req *subreq = NULL;
14979
14980         req = tevent_req_create(mem_ctx,
14981                                 &state,
14982                                 struct smb1_negotiate_exit_state);
14983         if (req == NULL) {
14984                 return NULL;
14985         }
14986         subreq = smb1cli_req_send(state, ev, conn,
14987                                   SMBexit,
14988                                   0, /*  additional_flags */
14989                                   0, /*  clear_flags */
14990                                   0, /*  additional_flags2 */
14991                                   0, /*  clear_flags2 */
14992                                   10000, /* timeout_msec */
14993                                   getpid(),
14994                                   NULL, /* tcon */
14995                                   NULL, /* session */
14996                                   0, /* wct */
14997                                   NULL,
14998                                   0,
14999                                   NULL);
15000         if (tevent_req_nomem(subreq, req)) {
15001                 return tevent_req_post(req, ev);
15002         }
15003         tevent_req_set_callback(subreq,
15004                                 smb1_negotiate_exit_done,
15005                                 req);
15006         return req;
15007 }
15008
15009 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15010 {
15011         struct tevent_req *req =
15012                 tevent_req_callback_data(subreq,
15013                 struct tevent_req);
15014         struct smb1_negotiate_exit_state *state =
15015                 tevent_req_data(req,
15016                 struct smb1_negotiate_exit_state);
15017         NTSTATUS status;
15018         struct smb1cli_req_expected_response expected[] = {
15019         {
15020                 .status = NT_STATUS_OK,
15021                 .wct    = 0,
15022         },
15023         };
15024
15025         status = smb1cli_req_recv(subreq, state,
15026                                   NULL,
15027                                   NULL,
15028                                   NULL,
15029                                   NULL,
15030                                   NULL, /* pvwv_offset */
15031                                   NULL,
15032                                   NULL,
15033                                   NULL, /* pbytes_offset */
15034                                   NULL,
15035                                   expected, ARRAY_SIZE(expected));
15036         TALLOC_FREE(subreq);
15037         if (tevent_req_nterror(req, status)) {
15038                 return;
15039         }
15040         tevent_req_done(req);
15041 }
15042
15043 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15044 {
15045         return tevent_req_simple_recv_ntstatus(req);
15046 }
15047
15048 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15049                          struct tevent_context *ev,
15050                          struct smbXcli_conn *conn)
15051 {
15052         struct tevent_req *req;
15053         bool ok;
15054         NTSTATUS status;
15055         NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15056
15057         req = smb1_negotiate_exit_send(ev, ev, conn);
15058         if (req == NULL) {
15059                 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15060                 return false;
15061         }
15062
15063         ok = tevent_req_poll_ntstatus(req, ev, &status);
15064         if (!ok) {
15065                 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15066                         nt_errstr(status));
15067                 return false;
15068         }
15069
15070         status = smb1_negotiate_exit_recv(req);
15071         if (!NT_STATUS_EQUAL(status, expected_status)) {
15072                 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15073                           "%s, expected ERRSRV, ERRinvnid\n",
15074                           nt_errstr(status));
15075                 return false;
15076         }
15077         return true;
15078 }
15079
15080 static bool run_smb1_negotiate_exit(int dummy)
15081 {
15082         struct tevent_context *ev;
15083         struct smbXcli_conn *conn;
15084         struct sockaddr_storage ss;
15085         NTSTATUS status;
15086         int fd;
15087         bool ok;
15088
15089         printf("Starting send SMB1 negotiate+exit.\n");
15090
15091         ok = resolve_name(host, &ss, 0x20, true);
15092         if (!ok) {
15093                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15094                 return false;
15095         }
15096
15097         status = open_socket_out(&ss, 445, 10000, &fd);
15098         if (!NT_STATUS_IS_OK(status)) {
15099                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15100                           nt_errstr(status));
15101                 return false;
15102         }
15103
15104         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15105                                    NULL, 0, NULL);
15106         if (conn == NULL) {
15107                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15108                 return false;
15109         }
15110
15111         status = smbXcli_negprot(conn,
15112                                  0,
15113                                  PROTOCOL_NT1,
15114                                  PROTOCOL_NT1,
15115                                  NULL,
15116                                  NULL,
15117                                  NULL);
15118         if (!NT_STATUS_IS_OK(status)) {
15119                 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15120                 return false;
15121         }
15122
15123         ev = samba_tevent_context_init(talloc_tos());
15124         if (ev == NULL) {
15125                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15126                 return false;
15127         }
15128
15129         /*
15130          * Call do_smb1_exit twice to catch a server crash, the
15131          * server sends the first return code then crashes.
15132          */
15133         ok = do_smb1_exit(ev, ev, conn);
15134         if (!ok) {
15135                 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15136                 return false;
15137         }
15138         ok = do_smb1_exit(ev, ev, conn);
15139         if (!ok) {
15140                 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15141                 return false;
15142         }
15143
15144         TALLOC_FREE(conn);
15145         return true;
15146 }
15147
15148 static bool run_smb1_negotiate_tcon(int dummy)
15149 {
15150         struct cli_state *cli = NULL;
15151         uint16_t cnum = 0;
15152         uint16_t max_xmit = 0;
15153         NTSTATUS status;
15154
15155         printf("Starting send SMB1 negotiate+tcon.\n");
15156         cli = open_nbt_connection();
15157         if (cli == NULL) {
15158                 d_fprintf(stderr, "open_nbt_connection failed!\n");
15159                 return false;
15160         }
15161         smbXcli_conn_set_sockopt(cli->conn, sockops);
15162
15163         status = smbXcli_negprot(cli->conn,
15164                                  0,
15165                                  PROTOCOL_NT1,
15166                                  PROTOCOL_NT1,
15167                                  NULL,
15168                                  NULL,
15169                                  NULL);
15170         if (!NT_STATUS_IS_OK(status)) {
15171                 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15172                         nt_errstr(status));
15173                 return false;
15174         }
15175         status = cli_raw_tcon(cli,
15176                               share,
15177                               "",
15178                               "?????",
15179                               &max_xmit,
15180                               &cnum);
15181         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15182                 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15183                         "(should get NT_STATUS_ACCESS_DENIED)!\n",
15184                         nt_errstr(status));
15185                 return false;
15186         }
15187         return true;
15188 }
15189
15190 static bool run_ign_bad_negprot(int dummy)
15191 {
15192         struct tevent_context *ev;
15193         struct tevent_req *req;
15194         struct smbXcli_conn *conn;
15195         struct sockaddr_storage ss;
15196         NTSTATUS status;
15197         int fd;
15198         bool ok;
15199
15200         printf("starting ignore bad negprot\n");
15201
15202         ok = resolve_name(host, &ss, 0x20, true);
15203         if (!ok) {
15204                 d_fprintf(stderr, "Could not resolve name %s\n", host);
15205                 return false;
15206         }
15207
15208         status = open_socket_out(&ss, 445, 10000, &fd);
15209         if (!NT_STATUS_IS_OK(status)) {
15210                 d_fprintf(stderr, "open_socket_out failed: %s\n",
15211                           nt_errstr(status));
15212                 return false;
15213         }
15214
15215         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15216                                    NULL, 0, NULL);
15217         if (conn == NULL) {
15218                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15219                 return false;
15220         }
15221
15222         status = smbXcli_negprot(conn,
15223                                  0,
15224                                  PROTOCOL_CORE,
15225                                  PROTOCOL_CORE,
15226                                  NULL,
15227                                  NULL,
15228                                  NULL);
15229         if (NT_STATUS_IS_OK(status)) {
15230                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15231                 return false;
15232         }
15233
15234         ev = samba_tevent_context_init(talloc_tos());
15235         if (ev == NULL) {
15236                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15237                 return false;
15238         }
15239
15240         req = smb1cli_session_setup_nt1_send(
15241                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15242                 data_blob_null, data_blob_null, 0x40,
15243                 "Windows 2000 2195", "Windows 2000 5.0");
15244         if (req == NULL) {
15245                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15246                 return false;
15247         }
15248
15249         ok = tevent_req_poll_ntstatus(req, ev, &status);
15250         if (!ok) {
15251                 d_fprintf(stderr, "tevent_req_poll failed\n");
15252                 return false;
15253         }
15254
15255         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15256                                                 NULL, NULL);
15257         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15258                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15259                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
15260                           nt_errstr(status));
15261                 return false;
15262         }
15263
15264         TALLOC_FREE(conn);
15265
15266         printf("starting ignore bad negprot\n");
15267
15268         return true;
15269 }
15270
15271
15272 static double create_procs(bool (*fn)(int), bool *result)
15273 {
15274         int i, status;
15275         volatile pid_t *child_status;
15276         volatile bool *child_status_out;
15277         int synccount;
15278         int tries = 8;
15279         struct timeval start;
15280
15281         synccount = 0;
15282
15283         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15284         if (!child_status) {
15285                 printf("Failed to setup shared memory\n");
15286                 return -1;
15287         }
15288
15289         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15290         if (!child_status_out) {
15291                 printf("Failed to setup result status shared memory\n");
15292                 return -1;
15293         }
15294
15295         for (i = 0; i < torture_nprocs; i++) {
15296                 child_status[i] = 0;
15297                 child_status_out[i] = True;
15298         }
15299
15300         start = timeval_current();
15301
15302         for (i=0;i<torture_nprocs;i++) {
15303                 procnum = i;
15304                 if (fork() == 0) {
15305                         pid_t mypid = getpid();
15306                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15307
15308                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
15309
15310                         while (1) {
15311                                 if (torture_open_connection(&current_cli, i)) break;
15312                                 if (tries-- == 0) {
15313                                         printf("pid %d failed to start\n", (int)getpid());
15314                                         _exit(1);
15315                                 }
15316                                 smb_msleep(10); 
15317                         }
15318
15319                         child_status[i] = getpid();
15320
15321                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15322
15323                         child_status_out[i] = fn(i);
15324                         _exit(0);
15325                 }
15326         }
15327
15328         do {
15329                 synccount = 0;
15330                 for (i=0;i<torture_nprocs;i++) {
15331                         if (child_status[i]) synccount++;
15332                 }
15333                 if (synccount == torture_nprocs) break;
15334                 smb_msleep(10);
15335         } while (timeval_elapsed(&start) < 30);
15336
15337         if (synccount != torture_nprocs) {
15338                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15339                 *result = False;
15340                 return timeval_elapsed(&start);
15341         }
15342
15343         /* start the client load */
15344         start = timeval_current();
15345
15346         for (i=0;i<torture_nprocs;i++) {
15347                 child_status[i] = 0;
15348         }
15349
15350         printf("%d clients started\n", torture_nprocs);
15351
15352         for (i=0;i<torture_nprocs;i++) {
15353                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15354         }
15355
15356         printf("\n");
15357
15358         for (i=0;i<torture_nprocs;i++) {
15359                 if (!child_status_out[i]) {
15360                         *result = False;
15361                 }
15362         }
15363         return timeval_elapsed(&start);
15364 }
15365
15366 #define FLAG_MULTIPROC 1
15367
15368 static struct {
15369         const char *name;
15370         bool (*fn)(int);
15371         unsigned flags;
15372 } torture_ops[] = {
15373         {
15374                 .name = "FDPASS",
15375                 .fn   = run_fdpasstest,
15376         },
15377         {
15378                 .name = "LOCK1",
15379                 .fn   = run_locktest1,
15380         },
15381         {
15382                 .name = "LOCK2",
15383                 .fn   =  run_locktest2,
15384         },
15385         {
15386                 .name = "LOCK3",
15387                 .fn   =  run_locktest3,
15388         },
15389         {
15390                 .name = "LOCK4",
15391                 .fn   =  run_locktest4,
15392         },
15393         {
15394                 .name = "LOCK5",
15395                 .fn   =  run_locktest5,
15396         },
15397         {
15398                 .name = "LOCK6",
15399                 .fn   =  run_locktest6,
15400         },
15401         {
15402                 .name = "LOCK7",
15403                 .fn   =  run_locktest7,
15404         },
15405         {
15406                 .name = "LOCK8",
15407                 .fn   =  run_locktest8,
15408         },
15409         {
15410                 .name = "LOCK9A",
15411                 .fn   =  run_locktest9a,
15412         },
15413         {
15414                 .name = "LOCK9B",
15415                 .fn   =  run_locktest9b,
15416         },
15417         {
15418                 .name = "LOCK10",
15419                 .fn   =  run_locktest10,
15420         },
15421         {
15422                 .name = "LOCK11",
15423                 .fn   =  run_locktest11,
15424         },
15425         {
15426                 .name = "LOCK12",
15427                 .fn   =  run_locktest12,
15428         },
15429         {
15430                 .name = "LOCK13",
15431                 .fn   =  run_locktest13,
15432         },
15433         {
15434                 .name = "UNLINK",
15435                 .fn   = run_unlinktest,
15436         },
15437         {
15438                 .name = "BROWSE",
15439                 .fn   = run_browsetest,
15440         },
15441         {
15442                 .name = "ATTR",
15443                 .fn   =   run_attrtest,
15444         },
15445         {
15446                 .name = "TRANS2",
15447                 .fn   = run_trans2test,
15448         },
15449         {
15450                 .name  = "MAXFID",
15451                 .fn    = run_maxfidtest,
15452                 .flags = FLAG_MULTIPROC,
15453         },
15454         {
15455                 .name  = "TORTURE",
15456                 .fn    = run_torture,
15457                 .flags = FLAG_MULTIPROC,
15458         },
15459         {
15460                 .name  = "RANDOMIPC",
15461                 .fn    = run_randomipc,
15462         },
15463         {
15464                 .name  = "NEGNOWAIT",
15465                 .fn    = run_negprot_nowait,
15466         },
15467         {
15468                 .name  = "NBENCH",
15469                 .fn    =  run_nbench,
15470         },
15471         {
15472                 .name  = "NBENCH2",
15473                 .fn    = run_nbench2,
15474         },
15475         {
15476                 .name  = "OPLOCK1",
15477                 .fn    =  run_oplock1,
15478         },
15479         {
15480                 .name  = "OPLOCK2",
15481                 .fn    =  run_oplock2,
15482         },
15483         {
15484                 .name  = "OPLOCK4",
15485                 .fn    =  run_oplock4,
15486         },
15487 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15488         {
15489                 .name  = "OPLOCK5",
15490                 .fn    =  run_oplock5,
15491         },
15492 #endif
15493         {
15494                 .name  = "DIR",
15495                 .fn    =  run_dirtest,
15496         },
15497         {
15498                 .name  = "DIR1",
15499                 .fn    =  run_dirtest1,
15500         },
15501         {
15502                 .name  = "DIR-CREATETIME",
15503                 .fn    =  run_dir_createtime,
15504         },
15505         {
15506                 .name  = "DENY1",
15507                 .fn    =  torture_denytest1,
15508         },
15509         {
15510                 .name  = "DENY2",
15511                 .fn    =  torture_denytest2,
15512         },
15513         {
15514                 .name  = "TCON",
15515                 .fn    =  run_tcon_test,
15516         },
15517         {
15518                 .name  = "TCONDEV",
15519                 .fn    =  run_tcon_devtype_test,
15520         },
15521         {
15522                 .name  = "RW1",
15523                 .fn    =  run_readwritetest,
15524         },
15525         {
15526                 .name  = "RW2",
15527                 .fn    =  run_readwritemulti,
15528                 .flags = FLAG_MULTIPROC
15529         },
15530         {
15531                 .name  = "RW3",
15532                 .fn    =  run_readwritelarge,
15533         },
15534         {
15535                 .name  = "RW-SIGNING",
15536                 .fn    =  run_readwritelarge_signtest,
15537         },
15538         {
15539                 .name  = "OPEN",
15540                 .fn    = run_opentest,
15541         },
15542         {
15543                 .name  = "POSIX",
15544                 .fn    = run_simple_posix_open_test,
15545         },
15546         {
15547                 .name  = "POSIX-APPEND",
15548                 .fn    = run_posix_append,
15549         },
15550         {
15551                 .name  = "POSIX-SYMLINK-ACL",
15552                 .fn    = run_acl_symlink_test,
15553         },
15554         {
15555                 .name  = "POSIX-SYMLINK-EA",
15556                 .fn    = run_ea_symlink_test,
15557         },
15558         {
15559                 .name  = "POSIX-STREAM-DELETE",
15560                 .fn    = run_posix_stream_delete,
15561         },
15562         {
15563                 .name  = "POSIX-OFD-LOCK",
15564                 .fn    = run_posix_ofd_lock_test,
15565         },
15566         {
15567                 .name  = "POSIX-BLOCKING-LOCK",
15568                 .fn    = run_posix_blocking_lock,
15569         },
15570         {
15571                 .name  = "POSIX-MKDIR",
15572                 .fn    = run_posix_mkdir_test,
15573         },
15574         {
15575                 .name  = "POSIX-ACL-OPLOCK",
15576                 .fn    = run_posix_acl_oplock_test,
15577         },
15578         {
15579                 .name  = "POSIX-ACL-SHAREROOT",
15580                 .fn    = run_posix_acl_shareroot_test,
15581         },
15582         {
15583                 .name  = "POSIX-LS-WILDCARD",
15584                 .fn    = run_posix_ls_wildcard_test,
15585         },
15586         {
15587                 .name  = "POSIX-LS-SINGLE",
15588                 .fn    = run_posix_ls_single_test,
15589         },
15590         {
15591                 .name  = "POSIX-READLINK",
15592                 .fn    = run_posix_readlink_test,
15593         },
15594         {
15595                 .name  = "POSIX-STAT",
15596                 .fn    = run_posix_stat_test,
15597         },
15598         {
15599                 .name  = "POSIX-SYMLINK-PARENT",
15600                 .fn    = run_posix_symlink_parent_test,
15601         },
15602         {
15603                 .name  = "POSIX-SYMLINK-CHMOD",
15604                 .fn    = run_posix_symlink_chmod_test,
15605         },
15606         {
15607                 .name  = "POSIX-SYMLINK-RENAME",
15608                 .fn    = run_posix_symlink_rename_test,
15609         },
15610         {
15611                 .name  = "POSIX-DIR-DEFAULT-ACL",
15612                 .fn    = run_posix_dir_default_acl_test,
15613         },
15614         {
15615                 .name  = "POSIX-SYMLINK-GETPATHINFO",
15616                 .fn    = run_posix_symlink_getpathinfo_test,
15617         },
15618         {
15619                 .name  = "POSIX-SYMLINK-SETPATHINFO",
15620                 .fn    = run_posix_symlink_setpathinfo_test,
15621         },
15622         {
15623                 .name  = "WINDOWS-BAD-SYMLINK",
15624                 .fn    = run_symlink_open_test,
15625         },
15626         {
15627                 .name  = "SMB1-WILD-MANGLE-UNLINK",
15628                 .fn    = run_smb1_wild_mangle_unlink_test,
15629         },
15630         {
15631                 .name  = "SMB1-WILD-MANGLE-RENAME",
15632                 .fn    = run_smb1_wild_mangle_rename_test,
15633         },
15634         {
15635                 .name  = "CASE-INSENSITIVE-CREATE",
15636                 .fn    = run_case_insensitive_create,
15637         },
15638         {
15639                 .name  = "ASYNC-ECHO",
15640                 .fn    = run_async_echo,
15641         },
15642         {
15643                 .name  = "UID-REGRESSION-TEST",
15644                 .fn    = run_uid_regression_test,
15645         },
15646         {
15647                 .name  = "SHORTNAME-TEST",
15648                 .fn    = run_shortname_test,
15649         },
15650         {
15651                 .name  = "ADDRCHANGE",
15652                 .fn    = run_addrchange,
15653         },
15654 #if 1
15655         {
15656                 .name  = "OPENATTR",
15657                 .fn    = run_openattrtest,
15658         },
15659 #endif
15660         {
15661                 .name  = "XCOPY",
15662                 .fn    = run_xcopy,
15663         },
15664         {
15665                 .name  = "RENAME",
15666                 .fn    = run_rename,
15667         },
15668         {
15669                 .name  = "RENAME-ACCESS",
15670                 .fn    = run_rename_access,
15671         },
15672         {
15673                 .name  = "OWNER-RIGHTS",
15674                 .fn    = run_owner_rights,
15675         },
15676         {
15677                 .name  = "DELETE",
15678                 .fn    = run_deletetest,
15679         },
15680         {
15681                 .name  = "DELETE-STREAM",
15682                 .fn    = run_delete_stream,
15683         },
15684         {
15685                 .name  = "DELETE-PRINT",
15686                 .fn    = run_delete_print_test,
15687         },
15688         {
15689                 .name  = "DELETE-LN",
15690                 .fn    = run_deletetest_ln,
15691         },
15692         {
15693                 .name  = "PROPERTIES",
15694                 .fn    = run_properties,
15695         },
15696         {
15697                 .name  = "MANGLE",
15698                 .fn    = torture_mangle,
15699         },
15700         {
15701                 .name  = "MANGLE1",
15702                 .fn    = run_mangle1,
15703         },
15704         {
15705                 .name  = "MANGLE-ILLEGAL",
15706                 .fn    = run_mangle_illegal,
15707         },
15708         {
15709                 .name  = "W2K",
15710                 .fn    = run_w2ktest,
15711         },
15712         {
15713                 .name  = "TRANS2SCAN",
15714                 .fn    = torture_trans2_scan,
15715         },
15716         {
15717                 .name  = "NTTRANSSCAN",
15718                 .fn    = torture_nttrans_scan,
15719         },
15720         {
15721                 .name  = "UTABLE",
15722                 .fn    = torture_utable,
15723         },
15724         {
15725                 .name  = "CASETABLE",
15726                 .fn    = torture_casetable,
15727         },
15728         {
15729                 .name  = "ERRMAPEXTRACT",
15730                 .fn    = run_error_map_extract,
15731         },
15732         {
15733                 .name  = "PIPE_NUMBER",
15734                 .fn    = run_pipe_number,
15735         },
15736         {
15737                 .name  = "TCON2",
15738                 .fn    =  run_tcon2_test,
15739         },
15740         {
15741                 .name  = "IOCTL",
15742                 .fn    =  torture_ioctl_test,
15743         },
15744         {
15745                 .name  = "CHKPATH",
15746                 .fn    =  torture_chkpath_test,
15747         },
15748         {
15749                 .name  = "FDSESS",
15750                 .fn    = run_fdsesstest,
15751         },
15752         {
15753                 .name  = "EATEST",
15754                 .fn    = run_eatest,
15755         },
15756         {
15757                 .name  = "SESSSETUP_BENCH",
15758                 .fn    = run_sesssetup_bench,
15759         },
15760         {
15761                 .name  = "CHAIN1",
15762                 .fn    = run_chain1,
15763         },
15764         {
15765                 .name  = "CHAIN2",
15766                 .fn    = run_chain2,
15767         },
15768         {
15769                 .name  = "CHAIN3",
15770                 .fn    = run_chain3,
15771         },
15772         {
15773                 .name  = "WINDOWS-WRITE",
15774                 .fn    = run_windows_write,
15775         },
15776         {
15777                 .name  = "LARGE_READX",
15778                 .fn    = run_large_readx,
15779         },
15780         {
15781                 .name  = "MSDFS-ATTRIBUTE",
15782                 .fn    = run_msdfs_attribute,
15783         },
15784         {
15785                 .name  = "NTTRANS-CREATE",
15786                 .fn    = run_nttrans_create,
15787         },
15788         {
15789                 .name  = "NTTRANS-FSCTL",
15790                 .fn    = run_nttrans_fsctl,
15791         },
15792         {
15793                 .name  = "CLI_ECHO",
15794                 .fn    = run_cli_echo,
15795         },
15796         {
15797                 .name  = "CLI_SPLICE",
15798                 .fn    = run_cli_splice,
15799         },
15800         {
15801                 .name  = "TLDAP",
15802                 .fn    = run_tldap,
15803         },
15804         {
15805                 .name  = "STREAMERROR",
15806                 .fn    = run_streamerror,
15807         },
15808         {
15809                 .name  = "NOTIFY-BENCH",
15810                 .fn    = run_notify_bench,
15811         },
15812         {
15813                 .name  = "NOTIFY-BENCH2",
15814                 .fn    = run_notify_bench2,
15815         },
15816         {
15817                 .name  = "NOTIFY-BENCH3",
15818                 .fn    = run_notify_bench3,
15819         },
15820         {
15821                 .name  = "BAD-NBT-SESSION",
15822                 .fn    = run_bad_nbt_session,
15823         },
15824         {
15825                 .name  = "IGN-BAD-NEGPROT",
15826                 .fn    = run_ign_bad_negprot,
15827         },
15828         {
15829                 .name  = "SMB-ANY-CONNECT",
15830                 .fn    = run_smb_any_connect,
15831         },
15832         {
15833                 .name  = "NOTIFY-ONLINE",
15834                 .fn    = run_notify_online,
15835         },
15836         {
15837                 .name  = "SMB2-BASIC",
15838                 .fn    = run_smb2_basic,
15839         },
15840         {
15841                 .name  = "SMB2-NEGPROT",
15842                 .fn    = run_smb2_negprot,
15843         },
15844         {
15845                 .name  = "SMB2-ANONYMOUS",
15846                 .fn    = run_smb2_anonymous,
15847         },
15848         {
15849                 .name  = "SMB2-SESSION-RECONNECT",
15850                 .fn    = run_smb2_session_reconnect,
15851         },
15852         {
15853                 .name  = "SMB2-TCON-DEPENDENCE",
15854                 .fn    = run_smb2_tcon_dependence,
15855         },
15856         {
15857                 .name  = "SMB2-MULTI-CHANNEL",
15858                 .fn    = run_smb2_multi_channel,
15859         },
15860         {
15861                 .name  = "SMB2-SESSION-REAUTH",
15862                 .fn    = run_smb2_session_reauth,
15863         },
15864         {
15865                 .name  = "SMB2-FTRUNCATE",
15866                 .fn    = run_smb2_ftruncate,
15867         },
15868         {
15869                 .name  = "SMB2-DIR-FSYNC",
15870                 .fn    = run_smb2_dir_fsync,
15871         },
15872         {
15873                 .name  = "SMB2-PATH-SLASH",
15874                 .fn    = run_smb2_path_slash,
15875         },
15876         {
15877                 .name  = "SMB1-SYSTEM-SECURITY",
15878                 .fn    = run_smb1_system_security,
15879         },
15880         {
15881                 .name  = "SMB2-SACL",
15882                 .fn    = run_smb2_sacl,
15883         },
15884         {
15885                 .name  = "SMB2-QUOTA1",
15886                 .fn    = run_smb2_quota1,
15887         },
15888         {
15889                 .name  = "SMB2-INVALID-PIPENAME",
15890                 .fn    = run_smb2_invalid_pipename,
15891         },
15892         {
15893                 .name  = "SMB2-STREAM-ACL",
15894                 .fn    = run_smb2_stream_acl,
15895         },
15896         {
15897                 .name  = "SMB2-LIST-DIR-ASYNC",
15898                 .fn    = run_list_dir_async_test,
15899         },
15900         {
15901                 .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15902                 .fn    = run_delete_on_close_non_empty,
15903         },
15904         {
15905                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15906                 .fn    = run_delete_on_close_nonwrite_delete_yes_test,
15907         },
15908         {
15909                 .name  = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15910                 .fn    = run_delete_on_close_nonwrite_delete_no_test,
15911         },
15912         {
15913                 .name  = "SMB2-DFS-PATHS",
15914                 .fn    = run_smb2_dfs_paths,
15915         },
15916         {
15917                 .name  = "SMB2-NON-DFS-SHARE",
15918                 .fn    = run_smb2_non_dfs_share,
15919         },
15920         {
15921                 .name  = "SMB2-DFS-SHARE-NON-DFS-PATH",
15922                 .fn    = run_smb2_dfs_share_non_dfs_path,
15923         },
15924         {
15925                 .name  = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15926                 .fn    = run_smb2_dfs_filename_leading_backslash,
15927         },
15928         {
15929                 .name  = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15930                 .fn    = run_smb2_pipe_read_async_disconnect,
15931         },
15932         {
15933                 .name  = "SMB1-TRUNCATED-SESSSETUP",
15934                 .fn    = run_smb1_truncated_sesssetup,
15935         },
15936         {
15937                 .name  = "SMB1-NEGOTIATE-EXIT",
15938                 .fn    = run_smb1_negotiate_exit,
15939         },
15940         {
15941                 .name  = "SMB1-NEGOTIATE-TCON",
15942                 .fn    = run_smb1_negotiate_tcon,
15943         },
15944         {
15945                 .name  = "SMB1-DFS-PATHS",
15946                 .fn    = run_smb1_dfs_paths,
15947         },
15948         {
15949                 .name  = "SMB1-DFS-SEARCH-PATHS",
15950                 .fn    = run_smb1_dfs_search_paths,
15951         },
15952         {
15953                 .name  = "SMB1-DFS-OPERATIONS",
15954                 .fn    = run_smb1_dfs_operations,
15955         },
15956         {
15957                 .name  = "SMB1-DFS-BADPATH",
15958                 .fn    = run_smb1_dfs_check_badpath,
15959         },
15960         {
15961                 .name  = "CLEANUP1",
15962                 .fn    = run_cleanup1,
15963         },
15964         {
15965                 .name  = "CLEANUP2",
15966                 .fn    = run_cleanup2,
15967         },
15968         {
15969                 .name  = "CLEANUP4",
15970                 .fn    = run_cleanup4,
15971         },
15972         {
15973                 .name  = "OPLOCK-CANCEL",
15974                 .fn    = run_oplock_cancel,
15975         },
15976         {
15977                 .name  = "PIDHIGH",
15978                 .fn    = run_pidhigh,
15979         },
15980         {
15981                 .name  = "LOCAL-SUBSTITUTE",
15982                 .fn    = run_local_substitute,
15983         },
15984         {
15985                 .name  = "LOCAL-GENCACHE",
15986                 .fn    = run_local_gencache,
15987         },
15988         {
15989                 .name  = "LOCAL-DBWRAP-WATCH1",
15990                 .fn    = run_dbwrap_watch1,
15991         },
15992         {
15993                 .name  = "LOCAL-DBWRAP-WATCH2",
15994                 .fn    = run_dbwrap_watch2,
15995         },
15996         {
15997                 .name  = "LOCAL-DBWRAP-WATCH3",
15998                 .fn    = run_dbwrap_watch3,
15999         },
16000         {
16001                 .name  = "LOCAL-DBWRAP-WATCH4",
16002                 .fn    = run_dbwrap_watch4,
16003         },
16004         {
16005                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
16006                 .fn    = run_dbwrap_do_locked1,
16007         },
16008         {
16009                 .name  = "LOCAL-MESSAGING-READ1",
16010                 .fn    = run_messaging_read1,
16011         },
16012         {
16013                 .name  = "LOCAL-MESSAGING-READ2",
16014                 .fn    = run_messaging_read2,
16015         },
16016         {
16017                 .name  = "LOCAL-MESSAGING-READ3",
16018                 .fn    = run_messaging_read3,
16019         },
16020         {
16021                 .name  = "LOCAL-MESSAGING-READ4",
16022                 .fn    = run_messaging_read4,
16023         },
16024         {
16025                 .name  = "LOCAL-MESSAGING-FDPASS1",
16026                 .fn    = run_messaging_fdpass1,
16027         },
16028         {
16029                 .name  = "LOCAL-MESSAGING-FDPASS2",
16030                 .fn    = run_messaging_fdpass2,
16031         },
16032         {
16033                 .name  = "LOCAL-MESSAGING-FDPASS2a",
16034                 .fn    = run_messaging_fdpass2a,
16035         },
16036         {
16037                 .name  = "LOCAL-MESSAGING-FDPASS2b",
16038                 .fn    = run_messaging_fdpass2b,
16039         },
16040         {
16041                 .name  = "LOCAL-MESSAGING-SEND-ALL",
16042                 .fn    = run_messaging_send_all,
16043         },
16044         {
16045                 .name  = "LOCAL-BASE64",
16046                 .fn    = run_local_base64,
16047         },
16048         {
16049                 .name  = "LOCAL-RBTREE",
16050                 .fn    = run_local_rbtree,
16051         },
16052         {
16053                 .name  = "LOCAL-MEMCACHE",
16054                 .fn    = run_local_memcache,
16055         },
16056         {
16057                 .name  = "LOCAL-STREAM-NAME",
16058                 .fn    = run_local_stream_name,
16059         },
16060         {
16061                 .name  = "LOCAL-STR-MATCH-MSWILD",
16062                 .fn    = run_str_match_mswild,
16063         },
16064         {
16065                 .name  = "LOCAL-STR-MATCH-REGEX-SUB1",
16066                 .fn    = run_str_match_regex_sub1,
16067         },
16068         {
16069                 .name  = "WBCLIENT-MULTI-PING",
16070                 .fn    = run_wbclient_multi_ping,
16071         },
16072         {
16073                 .name  = "LOCAL-string_to_sid",
16074                 .fn    = run_local_string_to_sid,
16075         },
16076         {
16077                 .name  = "LOCAL-sid_to_string",
16078                 .fn    = run_local_sid_to_string,
16079         },
16080         {
16081                 .name  = "LOCAL-binary_to_sid",
16082                 .fn    = run_local_binary_to_sid,
16083         },
16084         {
16085                 .name  = "LOCAL-DBTRANS",
16086                 .fn    = run_local_dbtrans,
16087         },
16088         {
16089                 .name  = "LOCAL-TEVENT-POLL",
16090                 .fn    = run_local_tevent_poll,
16091         },
16092         {
16093                 .name  = "LOCAL-CONVERT-STRING",
16094                 .fn    = run_local_convert_string,
16095         },
16096         {
16097                 .name  = "LOCAL-CONV-AUTH-INFO",
16098                 .fn    = run_local_conv_auth_info,
16099         },
16100         {
16101                 .name  = "LOCAL-hex_encode_buf",
16102                 .fn    = run_local_hex_encode_buf,
16103         },
16104         {
16105                 .name  = "LOCAL-IDMAP-TDB-COMMON",
16106                 .fn    = run_idmap_tdb_common_test,
16107         },
16108         {
16109                 .name  = "LOCAL-remove_duplicate_addrs2",
16110                 .fn    = run_local_remove_duplicate_addrs2,
16111         },
16112         {
16113                 .name  = "local-tdb-opener",
16114                 .fn    = run_local_tdb_opener,
16115         },
16116         {
16117                 .name  = "local-tdb-writer",
16118                 .fn    = run_local_tdb_writer,
16119         },
16120         {
16121                 .name  = "LOCAL-DBWRAP-CTDB1",
16122                 .fn    = run_local_dbwrap_ctdb1,
16123         },
16124         {
16125                 .name  = "LOCAL-BENCH-PTHREADPOOL",
16126                 .fn    = run_bench_pthreadpool,
16127         },
16128         {
16129                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
16130                 .fn    = run_pthreadpool_tevent,
16131         },
16132         {
16133                 .name  = "LOCAL-G-LOCK1",
16134                 .fn    = run_g_lock1,
16135         },
16136         {
16137                 .name  = "LOCAL-G-LOCK2",
16138                 .fn    = run_g_lock2,
16139         },
16140         {
16141                 .name  = "LOCAL-G-LOCK3",
16142                 .fn    = run_g_lock3,
16143         },
16144         {
16145                 .name  = "LOCAL-G-LOCK4",
16146                 .fn    = run_g_lock4,
16147         },
16148         {
16149                 .name  = "LOCAL-G-LOCK4A",
16150                 .fn    = run_g_lock4a,
16151         },
16152         {
16153                 .name  = "LOCAL-G-LOCK5",
16154                 .fn    = run_g_lock5,
16155         },
16156         {
16157                 .name  = "LOCAL-G-LOCK6",
16158                 .fn    = run_g_lock6,
16159         },
16160         {
16161                 .name  = "LOCAL-G-LOCK7",
16162                 .fn    = run_g_lock7,
16163         },
16164         {
16165                 .name  = "LOCAL-G-LOCK8",
16166                 .fn    = run_g_lock8,
16167         },
16168         {
16169                 .name  = "LOCAL-G-LOCK-PING-PONG",
16170                 .fn    = run_g_lock_ping_pong,
16171         },
16172         {
16173                 .name  = "LOCAL-CANONICALIZE-PATH",
16174                 .fn    = run_local_canonicalize_path,
16175         },
16176         {
16177                 .name  = "LOCAL-NAMEMAP-CACHE1",
16178                 .fn    = run_local_namemap_cache1,
16179         },
16180         {
16181                 .name  = "LOCAL-IDMAP-CACHE1",
16182                 .fn    = run_local_idmap_cache1,
16183         },
16184         {
16185                 .name  = "qpathinfo-bufsize",
16186                 .fn    = run_qpathinfo_bufsize,
16187         },
16188         {
16189                 .name  = "hide-new-files-timeout",
16190                 .fn    = run_hidenewfiles,
16191         },
16192         {
16193                 .name  = "hide-new-files-timeout-showdirs",
16194                 .fn    = run_hidenewfiles_showdirs,
16195         },
16196 #ifdef CLUSTER_SUPPORT
16197         {
16198                 .name  = "ctdbd-conn1",
16199                 .fn    = run_ctdbd_conn1,
16200         },
16201 #endif
16202         {
16203                 .name  = "readdir-timestamp",
16204                 .fn    = run_readdir_timestamp,
16205         },
16206         {
16207                 .name  = "rpc-scale",
16208                 .fn    = run_rpc_scale,
16209         },
16210         {
16211                 .name  = "LOCAL-TDB-VALIDATE",
16212                 .fn    = run_tdb_validate,
16213         },
16214         {
16215                 .name = NULL,
16216         },
16217 };
16218
16219 /****************************************************************************
16220 run a specified test or "ALL"
16221 ****************************************************************************/
16222 static bool run_test(const char *name)
16223 {
16224         bool ret = True;
16225         bool result = True;
16226         bool found = False;
16227         int i;
16228         double t;
16229         if (strequal(name,"ALL")) {
16230                 for (i=0;torture_ops[i].name;i++) {
16231                         run_test(torture_ops[i].name);
16232                 }
16233                 found = True;
16234         }
16235
16236         for (i=0;torture_ops[i].name;i++) {
16237                 fstr_sprintf(randomfname, "\\XX%x", 
16238                          (unsigned)random());
16239
16240                 if (strequal(name, torture_ops[i].name)) {
16241                         found = True;
16242                         printf("Running %s\n", name);
16243                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
16244                                 t = create_procs(torture_ops[i].fn, &result);
16245                                 if (!result) { 
16246                                         ret = False;
16247                                         printf("TEST %s FAILED!\n", name);
16248                                 }
16249                         } else {
16250                                 struct timeval start;
16251                                 start = timeval_current();
16252                                 if (!torture_ops[i].fn(0)) {
16253                                         ret = False;
16254                                         printf("TEST %s FAILED!\n", name);
16255                                 }
16256                                 t = timeval_elapsed(&start);
16257                         }
16258                         printf("%s took %g secs\n\n", name, t);
16259                 }
16260         }
16261
16262         if (!found) {
16263                 printf("Did not find a test named %s\n", name);
16264                 ret = False;
16265         }
16266
16267         return ret;
16268 }
16269
16270
16271 static void usage(void)
16272 {
16273         int i;
16274
16275         printf("WARNING samba4 test suite is much more complete nowadays.\n");
16276         printf("Please use samba4 torture.\n\n");
16277
16278         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16279
16280         printf("\t-d debuglevel\n");
16281         printf("\t-U user%%pass\n");
16282         printf("\t-k                    use kerberos\n");
16283         printf("\t-N numprocs\n");
16284         printf("\t-n my_netbios_name\n");
16285         printf("\t-W workgroup\n");
16286         printf("\t-o num_operations\n");
16287         printf("\t-O socket_options\n");
16288         printf("\t-m maximum protocol\n");
16289         printf("\t-L use oplocks\n");
16290         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
16291         printf("\t-A showall\n");
16292         printf("\t-p port\n");
16293         printf("\t-s seed\n");
16294         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
16295         printf("\t-f filename           filename to test\n");
16296         printf("\t-e                    encrypt\n");
16297         printf("\t-T 'OPTION=VALUE'     smb.conf option line\n");
16298         printf("\n\n");
16299
16300         printf("tests are:");
16301         for (i=0;torture_ops[i].name;i++) {
16302                 printf(" %s", torture_ops[i].name);
16303         }
16304         printf("\n");
16305
16306         printf("default test is ALL\n");
16307
16308         exit(1);
16309 }
16310
16311 /****************************************************************************
16312   main program
16313 ****************************************************************************/
16314  int main(int argc,char *argv[])
16315 {
16316         int opt, i;
16317         char *p;
16318         int gotuser = 0;
16319         int gotpass = 0;
16320         bool correct = True;
16321         TALLOC_CTX *frame = talloc_stackframe();
16322         int seed = time(NULL);
16323         struct loadparm_context *lp_ctx = NULL;
16324
16325 #ifdef HAVE_SETBUFFER
16326         setbuffer(stdout, NULL, 0);
16327 #endif
16328
16329         setup_logging("smbtorture", DEBUG_STDOUT);
16330
16331         smb_init_locale();
16332         fault_setup();
16333
16334         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16335         if (lp_ctx == NULL) {
16336                 fprintf(stderr,
16337                         "Failed to initialise the global parameter structure.\n");
16338                 return 1;
16339         }
16340
16341         if (is_default_dyn_CONFIGFILE()) {
16342                 if(getenv("SMB_CONF_PATH")) {
16343                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16344                 }
16345         }
16346         lp_load_global(get_dyn_CONFIGFILE());
16347         load_interfaces();
16348
16349         if (argc < 2) {
16350                 usage();
16351         }
16352
16353         for(p = argv[1]; *p; p++)
16354           if(*p == '\\')
16355             *p = '/';
16356
16357         if (strncmp(argv[1], "//", 2)) {
16358                 usage();
16359         }
16360
16361         fstrcpy(host, &argv[1][2]);
16362         p = strchr_m(&host[2],'/');
16363         if (!p) {
16364                 usage();
16365         }
16366         *p = 0;
16367         fstrcpy(share, p+1);
16368
16369         fstrcpy(myname, get_myname(talloc_tos()));
16370         if (!*myname) {
16371                 fprintf(stderr, "Failed to get my hostname.\n");
16372                 return 1;
16373         }
16374
16375         if (*username == 0 && getenv("LOGNAME")) {
16376           fstrcpy(username,getenv("LOGNAME"));
16377         }
16378
16379         argc--;
16380         argv++;
16381
16382         fstrcpy(workgroup, lp_workgroup());
16383
16384         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16385                != EOF) {
16386                 switch (opt) {
16387                 case 'p':
16388                         port_to_use = atoi(optarg);
16389                         break;
16390                 case 's':
16391                         seed = atoi(optarg);
16392                         break;
16393                 case 'W':
16394                         fstrcpy(workgroup,optarg);
16395                         break;
16396                 case 'm':
16397                         lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16398                         break;
16399                 case 'N':
16400                         torture_nprocs = atoi(optarg);
16401                         break;
16402                 case 'o':
16403                         torture_numops = atoi(optarg);
16404                         break;
16405                 case 'd':
16406                         lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16407                         break;
16408                 case 'O':
16409                         sockops = optarg;
16410                         break;
16411                 case 'L':
16412                         use_oplocks = True;
16413                         break;
16414                 case 'l':
16415                         local_path = optarg;
16416                         break;
16417                 case 'A':
16418                         torture_showall = True;
16419                         break;
16420                 case 'n':
16421                         fstrcpy(myname, optarg);
16422                         break;
16423                 case 'c':
16424                         client_txt = optarg;
16425                         break;
16426                 case 'e':
16427                         do_encrypt = true;
16428                         break;
16429                 case 'k':
16430 #ifdef HAVE_KRB5
16431                         use_kerberos = True;
16432 #else
16433                         d_printf("No kerberos support compiled in\n");
16434                         exit(1);
16435 #endif
16436                         break;
16437                 case 'U':
16438                         gotuser = 1;
16439                         fstrcpy(username,optarg);
16440                         p = strchr_m(username,'%');
16441                         if (p) {
16442                                 *p = 0;
16443                                 fstrcpy(password, p+1);
16444                                 gotpass = 1;
16445                         }
16446                         break;
16447                 case 'b':
16448                         fstrcpy(multishare_conn_fname, optarg);
16449                         use_multishare_conn = True;
16450                         break;
16451                 case 'B':
16452                         torture_blocksize = atoi(optarg);
16453                         break;
16454                 case 'f':
16455                         test_filename = SMB_STRDUP(optarg);
16456                         break;
16457                 case 'T':
16458                         lpcfg_set_option(lp_ctx, optarg);
16459                         break;
16460                 default:
16461                         printf("Unknown option %c (%d)\n", (char)opt, opt);
16462                         usage();
16463                 }
16464         }
16465
16466         d_printf("using seed %d\n", seed);
16467
16468         srandom(seed);
16469
16470         if(use_kerberos && !gotuser) gotpass = True;
16471
16472         while (!gotpass) {
16473                 char pwd[256] = {0};
16474                 int rc;
16475
16476                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16477                 if (rc == 0) {
16478                         fstrcpy(password, pwd);
16479                         gotpass = 1;
16480                 }
16481         }
16482
16483         printf("host=%s share=%s user=%s myname=%s\n", 
16484                host, share, username, myname);
16485
16486         torture_creds = cli_session_creds_init(frame,
16487                                                username,
16488                                                workgroup,
16489                                                NULL, /* realm */
16490                                                password,
16491                                                use_kerberos,
16492                                                false, /* fallback_after_kerberos */
16493                                                false, /* use_ccache */
16494                                                false); /* password_is_nt_hash */
16495         if (torture_creds == NULL) {
16496                 d_printf("cli_session_creds_init() failed.\n");
16497                 exit(1);
16498         }
16499
16500         if (argc == optind) {
16501                 correct = run_test("ALL");
16502         } else {
16503                 for (i=optind;i<argc;i++) {
16504                         if (!run_test(argv[i])) {
16505                                 correct = False;
16506                         }
16507                 }
16508         }
16509
16510         TALLOC_FREE(frame);
16511
16512         if (correct) {
16513                 return(0);
16514         } else {
16515                 return(1);
16516         }
16517 }