lib: Make sid_parse return the parsed length
[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 "../librpc/gen_ndr/svcctl.h"
30 #include "../lib/util/memcache.h"
31 #include "nsswitch/winbind_client.h"
32 #include "dbwrap/dbwrap.h"
33 #include "dbwrap/dbwrap_open.h"
34 #include "dbwrap/dbwrap_rbt.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43 #include "../libcli/smb/smbXcli_base.h"
44 #include "lib/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
46 #include "lib/util/time.h"
47 #include "lib/crypto/md5.h"
48 #include "lib/gencache.h"
49
50 extern char *optarg;
51 extern int optind;
52
53 fstring host, workgroup, share, password, username, myname;
54 struct cli_credentials *torture_creds;
55 static const char *sockops="TCP_NODELAY";
56 int torture_nprocs=1;
57 static int port_to_use=0;
58 int torture_numops=100;
59 int torture_blocksize=1024*1024;
60 static int procnum; /* records process count number when forking */
61 static struct cli_state *current_cli;
62 static fstring randomfname;
63 static bool use_oplocks;
64 static bool use_level_II_oplocks;
65 static const char *client_txt = "client_oplocks.txt";
66 static bool disable_spnego;
67 static bool use_kerberos;
68 static bool force_dos_errors;
69 static fstring multishare_conn_fname;
70 static bool use_multishare_conn = False;
71 static bool do_encrypt;
72 static const char *local_path = NULL;
73 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
74 char *test_filename;
75
76 bool torture_showall = False;
77
78 static double create_procs(bool (*fn)(int), bool *result);
79
80 /********************************************************************
81  Ensure a connection is encrypted.
82 ********************************************************************/
83
84 static bool force_cli_encryption(struct cli_state *c,
85                         const char *sharename)
86 {
87         uint16_t major, minor;
88         uint32_t caplow, caphigh;
89         NTSTATUS status;
90
91         if (!SERVER_HAS_UNIX_CIFS(c)) {
92                 d_printf("Encryption required and "
93                         "server that doesn't support "
94                         "UNIX extensions - failing connect\n");
95                         return false;
96         }
97
98         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
99                                              &caphigh);
100         if (!NT_STATUS_IS_OK(status)) {
101                 d_printf("Encryption required and "
102                         "can't get UNIX CIFS extensions "
103                         "version from server: %s\n", nt_errstr(status));
104                 return false;
105         }
106
107         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
108                 d_printf("Encryption required and "
109                         "share %s doesn't support "
110                         "encryption.\n", sharename);
111                 return false;
112         }
113
114         status = cli_smb1_setup_encryption(c, torture_creds);
115         if (!NT_STATUS_IS_OK(status)) {
116                 d_printf("Encryption required and "
117                         "setup failed with error %s.\n",
118                         nt_errstr(status));
119                 return false;
120         }
121
122         return true;
123 }
124
125
126 static struct cli_state *open_nbt_connection(void)
127 {
128         struct cli_state *c;
129         NTSTATUS status;
130         int flags = 0;
131
132         if (disable_spnego) {
133                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
134         }
135
136         if (use_oplocks) {
137                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
138         }
139
140         if (use_level_II_oplocks) {
141                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
142         }
143
144         if (use_kerberos) {
145                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
146         }
147
148         if (force_dos_errors) {
149                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
150         }
151
152         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
153                                 signing_state, flags, &c);
154         if (!NT_STATUS_IS_OK(status)) {
155                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
156                 return NULL;
157         }
158
159         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
160
161         return c;
162 }
163
164 /****************************************************************************
165  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
166 ****************************************************************************/
167
168 static bool cli_bad_session_request(int fd,
169                          struct nmb_name *calling, struct nmb_name *called)
170 {
171         TALLOC_CTX *frame;
172         uint8_t len_buf[4];
173         struct iovec iov[3];
174         ssize_t len;
175         uint8_t *inbuf;
176         int err;
177         bool ret = false;
178         uint8_t message_type;
179         uint8_t error;
180         struct tevent_context *ev;
181         struct tevent_req *req;
182
183         frame = talloc_stackframe();
184
185         iov[0].iov_base = len_buf;
186         iov[0].iov_len  = sizeof(len_buf);
187
188         /* put in the destination name */
189
190         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
191                                       called->name_type);
192         if (iov[1].iov_base == NULL) {
193                 goto fail;
194         }
195         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
196                                   talloc_get_size(iov[1].iov_base));
197
198         /* and my name */
199
200         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
201                                       calling->name_type);
202         if (iov[2].iov_base == NULL) {
203                 goto fail;
204         }
205         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
206                                   talloc_get_size(iov[2].iov_base));
207
208         /* Deliberately corrupt the name len (first byte) */
209         *((uint8_t *)iov[2].iov_base) = 100;
210
211         /* send a session request (RFC 1002) */
212         /* setup the packet length
213          * Remove four bytes from the length count, since the length
214          * field in the NBT Session Service header counts the number
215          * of bytes which follow.  The cli_send_smb() function knows
216          * about this and accounts for those four bytes.
217          * CRH.
218          */
219
220         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
221         SCVAL(len_buf,0,0x81);
222
223         len = write_data_iov(fd, iov, 3);
224         if (len == -1) {
225                 goto fail;
226         }
227
228         ev = samba_tevent_context_init(frame);
229         if (ev == NULL) {
230                 goto fail;
231         }
232         req = read_smb_send(frame, ev, fd);
233         if (req == NULL) {
234                 goto fail;
235         }
236         if (!tevent_req_poll(req, ev)) {
237                 goto fail;
238         }
239         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
240         if (len == -1) {
241                 errno = err;
242                 goto fail;
243         }
244         TALLOC_FREE(ev);
245
246         message_type = CVAL(inbuf, 0);
247         if (message_type != 0x83) {
248                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
249                           message_type);
250                 goto fail;
251         }
252
253         if (smb_len(inbuf) != 1) {
254                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
255                           (int)smb_len(inbuf));
256                 goto fail;
257         }
258
259         error = CVAL(inbuf, 4);
260         if (error !=  0x82) {
261                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
262                           (int)error);
263                 goto fail;
264         }
265
266         ret = true;
267 fail:
268         TALLOC_FREE(frame);
269         return ret;
270 }
271
272 /* Insert a NULL at the first separator of the given path and return a pointer
273  * to the remainder of the string.
274  */
275 static char *
276 terminate_path_at_separator(char * path)
277 {
278         char * p;
279
280         if (!path) {
281                 return NULL;
282         }
283
284         if ((p = strchr_m(path, '/'))) {
285                 *p = '\0';
286                 return p + 1;
287         }
288
289         if ((p = strchr_m(path, '\\'))) {
290                 *p = '\0';
291                 return p + 1;
292         }
293
294         /* No separator. */
295         return NULL;
296 }
297
298 /*
299   parse a //server/share type UNC name
300 */
301 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
302                       char **hostname, char **sharename)
303 {
304         char *p;
305
306         *hostname = *sharename = NULL;
307
308         if (strncmp(unc_name, "\\\\", 2) &&
309             strncmp(unc_name, "//", 2)) {
310                 return False;
311         }
312
313         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
314         p = terminate_path_at_separator(*hostname);
315
316         if (p && *p) {
317                 *sharename = talloc_strdup(mem_ctx, p);
318                 terminate_path_at_separator(*sharename);
319         }
320
321         if (*hostname && *sharename) {
322                 return True;
323         }
324
325         TALLOC_FREE(*hostname);
326         TALLOC_FREE(*sharename);
327         return False;
328 }
329
330 static bool torture_open_connection_share(struct cli_state **c,
331                                    const char *hostname, 
332                                    const char *sharename,
333                                    int flags)
334 {
335         NTSTATUS status;
336
337         status = cli_full_connection_creds(c,
338                                            myname,
339                                            hostname,
340                                            NULL, /* dest_ss */
341                                            port_to_use,
342                                            sharename,
343                                            "?????",
344                                            torture_creds,
345                                            flags,
346                                            signing_state);
347         if (!NT_STATUS_IS_OK(status)) {
348                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
349                         hostname, sharename, port_to_use, nt_errstr(status));
350                 return False;
351         }
352
353         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
354
355         if (do_encrypt) {
356                 return force_cli_encryption(*c,
357                                         sharename);
358         }
359         return True;
360 }
361
362 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
363 {
364         char **unc_list = NULL;
365         int num_unc_names = 0;
366         bool result;
367
368         if (use_multishare_conn==True) {
369                 char *h, *s;
370                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
371                 if (!unc_list || num_unc_names <= 0) {
372                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
373                         exit(1);
374                 }
375
376                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
377                                       NULL, &h, &s)) {
378                         printf("Failed to parse UNC name %s\n",
379                                unc_list[conn_index % num_unc_names]);
380                         TALLOC_FREE(unc_list);
381                         exit(1);
382                 }
383
384                 result = torture_open_connection_share(c, h, s, flags);
385
386                 /* h, s were copied earlier */
387                 TALLOC_FREE(unc_list);
388                 return result;
389         }
390
391         return torture_open_connection_share(c, host, share, flags);
392 }
393
394 bool torture_open_connection(struct cli_state **c, int conn_index)
395 {
396         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
397
398         if (use_oplocks) {
399                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
400         }
401         if (use_level_II_oplocks) {
402                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
403         }
404
405         return torture_open_connection_flags(c, conn_index, flags);
406 }
407
408 bool torture_init_connection(struct cli_state **pcli)
409 {
410         struct cli_state *cli;
411
412         cli = open_nbt_connection();
413         if (cli == NULL) {
414                 return false;
415         }
416
417         *pcli = cli;
418         return true;
419 }
420
421 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
422 {
423         uint16_t old_vuid = cli_state_get_uid(cli);
424         NTSTATUS status;
425         bool ret;
426
427         cli_state_set_uid(cli, 0);
428         status = cli_session_setup_creds(cli, torture_creds);
429         ret = NT_STATUS_IS_OK(status);
430         *new_vuid = cli_state_get_uid(cli);
431         cli_state_set_uid(cli, old_vuid);
432         return ret;
433 }
434
435
436 bool torture_close_connection(struct cli_state *c)
437 {
438         bool ret = True;
439         NTSTATUS status;
440
441         status = cli_tdis(c);
442         if (!NT_STATUS_IS_OK(status)) {
443                 printf("tdis failed (%s)\n", nt_errstr(status));
444                 ret = False;
445         }
446
447         cli_shutdown(c);
448
449         return ret;
450 }
451
452
453 /* check if the server produced the expected dos or nt error code */
454 static bool check_both_error(int line, NTSTATUS status,
455                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
456 {
457         if (NT_STATUS_IS_DOS(status)) {
458                 uint8_t cclass;
459                 uint32_t num;
460
461                 /* Check DOS error */
462                 cclass = NT_STATUS_DOS_CLASS(status);
463                 num = NT_STATUS_DOS_CODE(status);
464
465                 if (eclass != cclass || ecode != num) {
466                         printf("unexpected error code class=%d code=%d\n",
467                                (int)cclass, (int)num);
468                         printf(" expected %d/%d %s (line=%d)\n",
469                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
470                         return false;
471                 }
472         } else {
473                 /* Check NT error */
474                 if (!NT_STATUS_EQUAL(nterr, status)) {
475                         printf("unexpected error code %s\n",
476                                 nt_errstr(status));
477                         printf(" expected %s (line=%d)\n",
478                                 nt_errstr(nterr), line);
479                         return false;
480                 }
481         }
482
483         return true;
484 }
485
486
487 /* check if the server produced the expected error code */
488 static bool check_error(int line, NTSTATUS status,
489                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
490 {
491         if (NT_STATUS_IS_DOS(status)) {
492                 uint8_t cclass;
493                 uint32_t num;
494
495                 /* Check DOS error */
496
497                 cclass = NT_STATUS_DOS_CLASS(status);
498                 num = NT_STATUS_DOS_CODE(status);
499
500                 if (eclass != cclass || ecode != num) {
501                         printf("unexpected error code class=%d code=%d\n", 
502                                (int)cclass, (int)num);
503                         printf(" expected %d/%d %s (line=%d)\n", 
504                                (int)eclass, (int)ecode, nt_errstr(nterr),
505                                line);
506                         return False;
507                 }
508
509         } else {
510                 /* Check NT error */
511
512                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
513                         printf("unexpected error code %s\n",
514                                nt_errstr(status));
515                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
516                                line);
517                         return False;
518                 }
519         }
520
521         return True;
522 }
523
524
525 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
526 {
527         NTSTATUS status;
528
529         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
530
531         while (!NT_STATUS_IS_OK(status)) {
532                 if (!check_both_error(__LINE__, status, ERRDOS,
533                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
534                         return false;
535                 }
536
537                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
538         }
539
540         return true;
541 }
542
543
544 static bool rw_torture(struct cli_state *c)
545 {
546         const char *lockfname = "\\torture.lck";
547         fstring fname;
548         uint16_t fnum;
549         uint16_t fnum2;
550         pid_t pid2, pid = getpid();
551         int i, j;
552         char buf[1024];
553         bool correct = True;
554         size_t nread = 0;
555         NTSTATUS status;
556
557         memset(buf, '\0', sizeof(buf));
558
559         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
560                          DENY_NONE, &fnum2);
561         if (!NT_STATUS_IS_OK(status)) {
562                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
563         }
564         if (!NT_STATUS_IS_OK(status)) {
565                 printf("open of %s failed (%s)\n",
566                        lockfname, nt_errstr(status));
567                 return False;
568         }
569
570         for (i=0;i<torture_numops;i++) {
571                 unsigned n = (unsigned)sys_random()%10;
572
573                 if (i % 10 == 0) {
574                         printf("%d\r", i); fflush(stdout);
575                 }
576                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
577
578                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
579                         return False;
580                 }
581
582                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
583                                   DENY_ALL, &fnum);
584                 if (!NT_STATUS_IS_OK(status)) {
585                         printf("open failed (%s)\n", nt_errstr(status));
586                         correct = False;
587                         break;
588                 }
589
590                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
591                                       sizeof(pid), NULL);
592                 if (!NT_STATUS_IS_OK(status)) {
593                         printf("write failed (%s)\n", nt_errstr(status));
594                         correct = False;
595                 }
596
597                 for (j=0;j<50;j++) {
598                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
599                                               sizeof(pid)+(j*sizeof(buf)),
600                                               sizeof(buf), NULL);
601                         if (!NT_STATUS_IS_OK(status)) {
602                                 printf("write failed (%s)\n",
603                                        nt_errstr(status));
604                                 correct = False;
605                         }
606                 }
607
608                 pid2 = 0;
609
610                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
611                                   &nread);
612                 if (!NT_STATUS_IS_OK(status)) {
613                         printf("read failed (%s)\n", nt_errstr(status));
614                         correct = false;
615                 } else if (nread != sizeof(pid)) {
616                         printf("read/write compare failed: "
617                                "recv %ld req %ld\n", (unsigned long)nread,
618                                (unsigned long)sizeof(pid));
619                         correct = false;
620                 }
621
622                 if (pid2 != pid) {
623                         printf("data corruption!\n");
624                         correct = False;
625                 }
626
627                 status = cli_close(c, fnum);
628                 if (!NT_STATUS_IS_OK(status)) {
629                         printf("close failed (%s)\n", nt_errstr(status));
630                         correct = False;
631                 }
632
633                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
634                 if (!NT_STATUS_IS_OK(status)) {
635                         printf("unlink failed (%s)\n", nt_errstr(status));
636                         correct = False;
637                 }
638
639                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
640                 if (!NT_STATUS_IS_OK(status)) {
641                         printf("unlock failed (%s)\n", nt_errstr(status));
642                         correct = False;
643                 }
644         }
645
646         cli_close(c, fnum2);
647         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
648
649         printf("%d\n", i);
650
651         return correct;
652 }
653
654 static bool run_torture(int dummy)
655 {
656         struct cli_state *cli;
657         bool ret;
658
659         cli = current_cli;
660
661         smbXcli_conn_set_sockopt(cli->conn, sockops);
662
663         ret = rw_torture(cli);
664
665         if (!torture_close_connection(cli)) {
666                 ret = False;
667         }
668
669         return ret;
670 }
671
672 static bool rw_torture3(struct cli_state *c, char *lockfname)
673 {
674         uint16_t fnum = (uint16_t)-1;
675         unsigned int i = 0;
676         char buf[131072];
677         char buf_rd[131072];
678         unsigned count;
679         unsigned countprev = 0;
680         size_t sent = 0;
681         bool correct = True;
682         NTSTATUS status = NT_STATUS_OK;
683
684         srandom(1);
685         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
686         {
687                 SIVAL(buf, i, sys_random());
688         }
689
690         if (procnum == 0)
691         {
692                 status = cli_unlink(
693                         c, lockfname,
694                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
695                 if (!NT_STATUS_IS_OK(status)) {
696                         printf("unlink failed (%s) (normal, this file should "
697                                "not exist)\n", nt_errstr(status));
698                 }
699
700                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
701                                   DENY_NONE, &fnum);
702                 if (!NT_STATUS_IS_OK(status)) {
703                         printf("first open read/write of %s failed (%s)\n",
704                                         lockfname, nt_errstr(status));
705                         return False;
706                 }
707         }
708         else
709         {
710                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
711                 {
712                         status = cli_openx(c, lockfname, O_RDONLY, 
713                                          DENY_NONE, &fnum);
714                         if (NT_STATUS_IS_OK(status)) {
715                                 break;
716                         }
717                         smb_msleep(10);
718                 }
719                 if (!NT_STATUS_IS_OK(status)) {
720                         printf("second open read-only of %s failed (%s)\n",
721                                         lockfname, nt_errstr(status));
722                         return False;
723                 }
724         }
725
726         i = 0;
727         for (count = 0; count < sizeof(buf); count += sent)
728         {
729                 if (count >= countprev) {
730                         printf("%d %8d\r", i, count);
731                         fflush(stdout);
732                         i++;
733                         countprev += (sizeof(buf) / 20);
734                 }
735
736                 if (procnum == 0)
737                 {
738                         sent = ((unsigned)sys_random()%(20))+ 1;
739                         if (sent > sizeof(buf) - count)
740                         {
741                                 sent = sizeof(buf) - count;
742                         }
743
744                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
745                                               count, sent, NULL);
746                         if (!NT_STATUS_IS_OK(status)) {
747                                 printf("write failed (%s)\n",
748                                        nt_errstr(status));
749                                 correct = False;
750                         }
751                 }
752                 else
753                 {
754                         status = cli_read(c, fnum, buf_rd+count, count,
755                                           sizeof(buf)-count, &sent);
756                         if(!NT_STATUS_IS_OK(status)) {
757                                 printf("read failed offset:%d size:%ld (%s)\n",
758                                        count, (unsigned long)sizeof(buf)-count,
759                                        nt_errstr(status));
760                                 correct = False;
761                                 sent = 0;
762                         } else if (sent > 0) {
763                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
764                                 {
765                                         printf("read/write compare failed\n");
766                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
767                                         correct = False;
768                                         break;
769                                 }
770                         }
771                 }
772
773         }
774
775         status = cli_close(c, fnum);
776         if (!NT_STATUS_IS_OK(status)) {
777                 printf("close failed (%s)\n", nt_errstr(status));
778                 correct = False;
779         }
780
781         return correct;
782 }
783
784 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
785 {
786         const char *lockfname = "\\torture2.lck";
787         uint16_t fnum1;
788         uint16_t fnum2;
789         int i;
790         char buf[131072];
791         char buf_rd[131072];
792         bool correct = True;
793         size_t bytes_read;
794         NTSTATUS status;
795
796         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
797         if (!NT_STATUS_IS_OK(status)) {
798                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
799         }
800
801         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
802                           DENY_NONE, &fnum1);
803         if (!NT_STATUS_IS_OK(status)) {
804                 printf("first open read/write of %s failed (%s)\n",
805                                 lockfname, nt_errstr(status));
806                 return False;
807         }
808
809         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
810         if (!NT_STATUS_IS_OK(status)) {
811                 printf("second open read-only of %s failed (%s)\n",
812                                 lockfname, nt_errstr(status));
813                 cli_close(c1, fnum1);
814                 return False;
815         }
816
817         for (i = 0; i < torture_numops; i++)
818         {
819                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
820                 if (i % 10 == 0) {
821                         printf("%d\r", i); fflush(stdout);
822                 }
823
824                 generate_random_buffer((unsigned char *)buf, buf_size);
825
826                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
827                                       buf_size, NULL);
828                 if (!NT_STATUS_IS_OK(status)) {
829                         printf("write failed (%s)\n", nt_errstr(status));
830                         correct = False;
831                         break;
832                 }
833
834                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
835                 if(!NT_STATUS_IS_OK(status)) {
836                         printf("read failed (%s)\n", nt_errstr(status));
837                         correct = false;
838                         break;
839                 } else if (bytes_read != buf_size) {
840                         printf("read failed\n");
841                         printf("read %ld, expected %ld\n",
842                                (unsigned long)bytes_read,
843                                (unsigned long)buf_size); 
844                         correct = False;
845                         break;
846                 }
847
848                 if (memcmp(buf_rd, buf, buf_size) != 0)
849                 {
850                         printf("read/write compare failed\n");
851                         correct = False;
852                         break;
853                 }
854         }
855
856         status = cli_close(c2, fnum2);
857         if (!NT_STATUS_IS_OK(status)) {
858                 printf("close failed (%s)\n", nt_errstr(status));
859                 correct = False;
860         }
861
862         status = cli_close(c1, fnum1);
863         if (!NT_STATUS_IS_OK(status)) {
864                 printf("close failed (%s)\n", nt_errstr(status));
865                 correct = False;
866         }
867
868         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
869         if (!NT_STATUS_IS_OK(status)) {
870                 printf("unlink failed (%s)\n", nt_errstr(status));
871                 correct = False;
872         }
873
874         return correct;
875 }
876
877 static bool run_readwritetest(int dummy)
878 {
879         struct cli_state *cli1, *cli2;
880         bool test1, test2 = False;
881
882         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
883                 return False;
884         }
885         smbXcli_conn_set_sockopt(cli1->conn, sockops);
886         smbXcli_conn_set_sockopt(cli2->conn, sockops);
887
888         printf("starting readwritetest\n");
889
890         test1 = rw_torture2(cli1, cli2);
891         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
892
893         if (test1) {
894                 test2 = rw_torture2(cli1, cli1);
895                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
896         }
897
898         if (!torture_close_connection(cli1)) {
899                 test1 = False;
900         }
901
902         if (!torture_close_connection(cli2)) {
903                 test2 = False;
904         }
905
906         return (test1 && test2);
907 }
908
909 static bool run_readwritemulti(int dummy)
910 {
911         struct cli_state *cli;
912         bool test;
913
914         cli = current_cli;
915
916         smbXcli_conn_set_sockopt(cli->conn, sockops);
917
918         printf("run_readwritemulti: fname %s\n", randomfname);
919         test = rw_torture3(cli, randomfname);
920
921         if (!torture_close_connection(cli)) {
922                 test = False;
923         }
924
925         return test;
926 }
927
928 static bool run_readwritelarge_internal(void)
929 {
930         static struct cli_state *cli1;
931         uint16_t fnum1;
932         const char *lockfname = "\\large.dat";
933         off_t fsize;
934         char buf[126*1024];
935         bool correct = True;
936         NTSTATUS status;
937
938         if (!torture_open_connection(&cli1, 0)) {
939                 return False;
940         }
941         smbXcli_conn_set_sockopt(cli1->conn, sockops);
942         memset(buf,'\0',sizeof(buf));
943
944         printf("starting readwritelarge_internal\n");
945
946         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
947
948         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
949                           DENY_NONE, &fnum1);
950         if (!NT_STATUS_IS_OK(status)) {
951                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
952                 return False;
953         }
954
955         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
956
957         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
958                                      NULL, NULL, NULL);
959         if (!NT_STATUS_IS_OK(status)) {
960                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
961                 correct = False;
962         }
963
964         if (fsize == sizeof(buf))
965                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
966                        (unsigned long)fsize);
967         else {
968                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
969                        (unsigned long)fsize);
970                 correct = False;
971         }
972
973         status = cli_close(cli1, fnum1);
974         if (!NT_STATUS_IS_OK(status)) {
975                 printf("close failed (%s)\n", nt_errstr(status));
976                 correct = False;
977         }
978
979         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
980         if (!NT_STATUS_IS_OK(status)) {
981                 printf("unlink failed (%s)\n", nt_errstr(status));
982                 correct = False;
983         }
984
985         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
986                           DENY_NONE, &fnum1);
987         if (!NT_STATUS_IS_OK(status)) {
988                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
989                 return False;
990         }
991
992         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
993
994         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
995                                      NULL, NULL, NULL);
996         if (!NT_STATUS_IS_OK(status)) {
997                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
998                 correct = False;
999         }
1000
1001         if (fsize == sizeof(buf))
1002                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1003                        (unsigned long)fsize);
1004         else {
1005                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1006                        (unsigned long)fsize);
1007                 correct = False;
1008         }
1009
1010 #if 0
1011         /* ToDo - set allocation. JRA */
1012         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1013                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1014                 return False;
1015         }
1016         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1017                                  NULL, NULL)) {
1018                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1019                 correct = False;
1020         }
1021         if (fsize != 0)
1022                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1023 #endif
1024
1025         status = cli_close(cli1, fnum1);
1026         if (!NT_STATUS_IS_OK(status)) {
1027                 printf("close failed (%s)\n", nt_errstr(status));
1028                 correct = False;
1029         }
1030
1031         if (!torture_close_connection(cli1)) {
1032                 correct = False;
1033         }
1034         return correct;
1035 }
1036
1037 static bool run_readwritelarge(int dummy)
1038 {
1039         return run_readwritelarge_internal();
1040 }
1041
1042 static bool run_readwritelarge_signtest(int dummy)
1043 {
1044         bool ret;
1045         signing_state = SMB_SIGNING_REQUIRED;
1046         ret = run_readwritelarge_internal();
1047         signing_state = SMB_SIGNING_DEFAULT;
1048         return ret;
1049 }
1050
1051 int line_count = 0;
1052 int nbio_id;
1053
1054 #define ival(s) strtol(s, NULL, 0)
1055
1056 /* run a test that simulates an approximate netbench client load */
1057 static bool run_netbench(int client)
1058 {
1059         struct cli_state *cli;
1060         int i;
1061         char line[1024];
1062         char cname[20];
1063         FILE *f;
1064         const char *params[20];
1065         bool correct = True;
1066
1067         cli = current_cli;
1068
1069         nbio_id = client;
1070
1071         smbXcli_conn_set_sockopt(cli->conn, sockops);
1072
1073         nb_setup(cli);
1074
1075         slprintf(cname,sizeof(cname)-1, "client%d", client);
1076
1077         f = fopen(client_txt, "r");
1078
1079         if (!f) {
1080                 perror(client_txt);
1081                 return False;
1082         }
1083
1084         while (fgets(line, sizeof(line)-1, f)) {
1085                 char *saveptr;
1086                 line_count++;
1087
1088                 line[strlen(line)-1] = 0;
1089
1090                 /* printf("[%d] %s\n", line_count, line); */
1091
1092                 all_string_sub(line,"client1", cname, sizeof(line));
1093
1094                 /* parse the command parameters */
1095                 params[0] = strtok_r(line, " ", &saveptr);
1096                 i = 0;
1097                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1098
1099                 params[i] = "";
1100
1101                 if (i < 2) continue;
1102
1103                 if (!strncmp(params[0],"SMB", 3)) {
1104                         printf("ERROR: You are using a dbench 1 load file\n");
1105                         exit(1);
1106                 }
1107
1108                 if (!strcmp(params[0],"NTCreateX")) {
1109                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1110                                    ival(params[4]));
1111                 } else if (!strcmp(params[0],"Close")) {
1112                         nb_close(ival(params[1]));
1113                 } else if (!strcmp(params[0],"Rename")) {
1114                         nb_rename(params[1], params[2]);
1115                 } else if (!strcmp(params[0],"Unlink")) {
1116                         nb_unlink(params[1]);
1117                 } else if (!strcmp(params[0],"Deltree")) {
1118                         nb_deltree(params[1]);
1119                 } else if (!strcmp(params[0],"Rmdir")) {
1120                         nb_rmdir(params[1]);
1121                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1122                         nb_qpathinfo(params[1]);
1123                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1124                         nb_qfileinfo(ival(params[1]));
1125                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1126                         nb_qfsinfo(ival(params[1]));
1127                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1128                         nb_findfirst(params[1]);
1129                 } else if (!strcmp(params[0],"WriteX")) {
1130                         nb_writex(ival(params[1]), 
1131                                   ival(params[2]), ival(params[3]), ival(params[4]));
1132                 } else if (!strcmp(params[0],"ReadX")) {
1133                         nb_readx(ival(params[1]), 
1134                                   ival(params[2]), ival(params[3]), ival(params[4]));
1135                 } else if (!strcmp(params[0],"Flush")) {
1136                         nb_flush(ival(params[1]));
1137                 } else {
1138                         printf("Unknown operation %s\n", params[0]);
1139                         exit(1);
1140                 }
1141         }
1142         fclose(f);
1143
1144         nb_cleanup();
1145
1146         if (!torture_close_connection(cli)) {
1147                 correct = False;
1148         }
1149
1150         return correct;
1151 }
1152
1153
1154 /* run a test that simulates an approximate netbench client load */
1155 static bool run_nbench(int dummy)
1156 {
1157         double t;
1158         bool correct = True;
1159
1160         nbio_shmem(torture_nprocs);
1161
1162         nbio_id = -1;
1163
1164         signal(SIGALRM, nb_alarm);
1165         alarm(1);
1166         t = create_procs(run_netbench, &correct);
1167         alarm(0);
1168
1169         printf("\nThroughput %g MB/sec\n", 
1170                1.0e-6 * nbio_total() / t);
1171         return correct;
1172 }
1173
1174
1175 /*
1176   This test checks for two things:
1177
1178   1) correct support for retaining locks over a close (ie. the server
1179      must not use posix semantics)
1180   2) support for lock timeouts
1181  */
1182 static bool run_locktest1(int dummy)
1183 {
1184         struct cli_state *cli1, *cli2;
1185         const char *fname = "\\lockt1.lck";
1186         uint16_t fnum1, fnum2, fnum3;
1187         time_t t1, t2;
1188         unsigned lock_timeout;
1189         NTSTATUS status;
1190
1191         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1192                 return False;
1193         }
1194         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1195         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1196
1197         printf("starting locktest1\n");
1198
1199         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1200
1201         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1202                           &fnum1);
1203         if (!NT_STATUS_IS_OK(status)) {
1204                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1205                 return False;
1206         }
1207
1208         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1209         if (!NT_STATUS_IS_OK(status)) {
1210                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1211                 return False;
1212         }
1213
1214         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1215         if (!NT_STATUS_IS_OK(status)) {
1216                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1217                 return False;
1218         }
1219
1220         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1221         if (!NT_STATUS_IS_OK(status)) {
1222                 printf("lock1 failed (%s)\n", nt_errstr(status));
1223                 return false;
1224         }
1225
1226         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1227         if (NT_STATUS_IS_OK(status)) {
1228                 printf("lock2 succeeded! This is a locking bug\n");
1229                 return false;
1230         } else {
1231                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1232                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1233                         return false;
1234                 }
1235         }
1236
1237         lock_timeout = (1 + (random() % 20));
1238         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1239         t1 = time(NULL);
1240         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1241         if (NT_STATUS_IS_OK(status)) {
1242                 printf("lock3 succeeded! This is a locking bug\n");
1243                 return false;
1244         } else {
1245                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1246                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1247                         return false;
1248                 }
1249         }
1250         t2 = time(NULL);
1251
1252         if (ABS(t2 - t1) < lock_timeout-1) {
1253                 printf("error: This server appears not to support timed lock requests\n");
1254         }
1255
1256         printf("server slept for %u seconds for a %u second timeout\n",
1257                (unsigned int)(t2-t1), lock_timeout);
1258
1259         status = cli_close(cli1, fnum2);
1260         if (!NT_STATUS_IS_OK(status)) {
1261                 printf("close1 failed (%s)\n", nt_errstr(status));
1262                 return False;
1263         }
1264
1265         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1266         if (NT_STATUS_IS_OK(status)) {
1267                 printf("lock4 succeeded! This is a locking bug\n");
1268                 return false;
1269         } else {
1270                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1271                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1272                         return false;
1273                 }
1274         }
1275
1276         status = cli_close(cli1, fnum1);
1277         if (!NT_STATUS_IS_OK(status)) {
1278                 printf("close2 failed (%s)\n", nt_errstr(status));
1279                 return False;
1280         }
1281
1282         status = cli_close(cli2, fnum3);
1283         if (!NT_STATUS_IS_OK(status)) {
1284                 printf("close3 failed (%s)\n", nt_errstr(status));
1285                 return False;
1286         }
1287
1288         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 printf("unlink failed (%s)\n", nt_errstr(status));
1291                 return False;
1292         }
1293
1294
1295         if (!torture_close_connection(cli1)) {
1296                 return False;
1297         }
1298
1299         if (!torture_close_connection(cli2)) {
1300                 return False;
1301         }
1302
1303         printf("Passed locktest1\n");
1304         return True;
1305 }
1306
1307 /*
1308   this checks to see if a secondary tconx can use open files from an
1309   earlier tconx
1310  */
1311 static bool run_tcon_test(int dummy)
1312 {
1313         static struct cli_state *cli;
1314         const char *fname = "\\tcontest.tmp";
1315         uint16_t fnum1;
1316         uint32_t cnum1, cnum2, cnum3;
1317         struct smbXcli_tcon *orig_tcon = NULL;
1318         uint16_t vuid1, vuid2;
1319         char buf[4];
1320         bool ret = True;
1321         NTSTATUS status;
1322
1323         memset(buf, '\0', sizeof(buf));
1324
1325         if (!torture_open_connection(&cli, 0)) {
1326                 return False;
1327         }
1328         smbXcli_conn_set_sockopt(cli->conn, sockops);
1329
1330         printf("starting tcontest\n");
1331
1332         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1333
1334         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1335         if (!NT_STATUS_IS_OK(status)) {
1336                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1337                 return False;
1338         }
1339
1340         cnum1 = cli_state_get_tid(cli);
1341         vuid1 = cli_state_get_uid(cli);
1342
1343         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1344         if (!NT_STATUS_IS_OK(status)) {
1345                 printf("initial write failed (%s)", nt_errstr(status));
1346                 return False;
1347         }
1348
1349         orig_tcon = cli_state_save_tcon(cli);
1350         if (orig_tcon == NULL) {
1351                 return false;
1352         }
1353
1354         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1355         if (!NT_STATUS_IS_OK(status)) {
1356                 printf("%s refused 2nd tree connect (%s)\n", host,
1357                        nt_errstr(status));
1358                 cli_shutdown(cli);
1359                 return False;
1360         }
1361
1362         cnum2 = cli_state_get_tid(cli);
1363         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1364         vuid2 = cli_state_get_uid(cli) + 1;
1365
1366         /* try a write with the wrong tid */
1367         cli_state_set_tid(cli, cnum2);
1368
1369         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1370         if (NT_STATUS_IS_OK(status)) {
1371                 printf("* server allows write with wrong TID\n");
1372                 ret = False;
1373         } else {
1374                 printf("server fails write with wrong TID : %s\n",
1375                        nt_errstr(status));
1376         }
1377
1378
1379         /* try a write with an invalid tid */
1380         cli_state_set_tid(cli, cnum3);
1381
1382         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1383         if (NT_STATUS_IS_OK(status)) {
1384                 printf("* server allows write with invalid TID\n");
1385                 ret = False;
1386         } else {
1387                 printf("server fails write with invalid TID : %s\n",
1388                        nt_errstr(status));
1389         }
1390
1391         /* try a write with an invalid vuid */
1392         cli_state_set_uid(cli, vuid2);
1393         cli_state_set_tid(cli, cnum1);
1394
1395         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1396         if (NT_STATUS_IS_OK(status)) {
1397                 printf("* server allows write with invalid VUID\n");
1398                 ret = False;
1399         } else {
1400                 printf("server fails write with invalid VUID : %s\n",
1401                        nt_errstr(status));
1402         }
1403
1404         cli_state_set_tid(cli, cnum1);
1405         cli_state_set_uid(cli, vuid1);
1406
1407         status = cli_close(cli, fnum1);
1408         if (!NT_STATUS_IS_OK(status)) {
1409                 printf("close failed (%s)\n", nt_errstr(status));
1410                 return False;
1411         }
1412
1413         cli_state_set_tid(cli, cnum2);
1414
1415         status = cli_tdis(cli);
1416         if (!NT_STATUS_IS_OK(status)) {
1417                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1418                 return False;
1419         }
1420
1421         cli_state_restore_tcon(cli, orig_tcon);
1422
1423         cli_state_set_tid(cli, cnum1);
1424
1425         if (!torture_close_connection(cli)) {
1426                 return False;
1427         }
1428
1429         return ret;
1430 }
1431
1432
1433 /*
1434  checks for old style tcon support
1435  */
1436 static bool run_tcon2_test(int dummy)
1437 {
1438         static struct cli_state *cli;
1439         uint16_t cnum, max_xmit;
1440         char *service;
1441         NTSTATUS status;
1442
1443         if (!torture_open_connection(&cli, 0)) {
1444                 return False;
1445         }
1446         smbXcli_conn_set_sockopt(cli->conn, sockops);
1447
1448         printf("starting tcon2 test\n");
1449
1450         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1451                 return false;
1452         }
1453
1454         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1455
1456         SAFE_FREE(service);
1457
1458         if (!NT_STATUS_IS_OK(status)) {
1459                 printf("tcon2 failed : %s\n", nt_errstr(status));
1460         } else {
1461                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1462                        (int)max_xmit, (int)cnum);
1463         }
1464
1465         if (!torture_close_connection(cli)) {
1466                 return False;
1467         }
1468
1469         printf("Passed tcon2 test\n");
1470         return True;
1471 }
1472
1473 static bool tcon_devtest(struct cli_state *cli,
1474                          const char *myshare, const char *devtype,
1475                          const char *return_devtype,
1476                          NTSTATUS expected_error)
1477 {
1478         NTSTATUS status;
1479         bool ret;
1480
1481         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1482
1483         if (NT_STATUS_IS_OK(expected_error)) {
1484                 if (NT_STATUS_IS_OK(status)) {
1485                         if (return_devtype != NULL &&
1486                             strequal(cli->dev, return_devtype)) {
1487                                 ret = True;
1488                         } else { 
1489                                 printf("tconX to share %s with type %s "
1490                                        "succeeded but returned the wrong "
1491                                        "device type (got [%s] but should have got [%s])\n",
1492                                        myshare, devtype, cli->dev, return_devtype);
1493                                 ret = False;
1494                         }
1495                 } else {
1496                         printf("tconX to share %s with type %s "
1497                                "should have succeeded but failed\n",
1498                                myshare, devtype);
1499                         ret = False;
1500                 }
1501                 cli_tdis(cli);
1502         } else {
1503                 if (NT_STATUS_IS_OK(status)) {
1504                         printf("tconx to share %s with type %s "
1505                                "should have failed but succeeded\n",
1506                                myshare, devtype);
1507                         ret = False;
1508                 } else {
1509                         if (NT_STATUS_EQUAL(status, expected_error)) {
1510                                 ret = True;
1511                         } else {
1512                                 printf("Returned unexpected error\n");
1513                                 ret = False;
1514                         }
1515                 }
1516         }
1517         return ret;
1518 }
1519
1520 /*
1521  checks for correct tconX support
1522  */
1523 static bool run_tcon_devtype_test(int dummy)
1524 {
1525         static struct cli_state *cli1 = NULL;
1526         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1527         NTSTATUS status;
1528         bool ret = True;
1529
1530         status = cli_full_connection_creds(&cli1,
1531                                            myname,
1532                                            host,
1533                                            NULL, /* dest_ss */
1534                                            port_to_use,
1535                                            NULL, /* service */
1536                                            NULL, /* service_type */
1537                                            torture_creds,
1538                                            flags,
1539                                            signing_state);
1540
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 printf("could not open connection\n");
1543                 return False;
1544         }
1545
1546         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1547                 ret = False;
1548
1549         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1550                 ret = False;
1551
1552         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1553                 ret = False;
1554
1555         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1556                 ret = False;
1557
1558         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1559                 ret = False;
1560
1561         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1562                 ret = False;
1563
1564         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1565                 ret = False;
1566
1567         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1568                 ret = False;
1569
1570         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1571                 ret = False;
1572
1573         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1574                 ret = False;
1575
1576         cli_shutdown(cli1);
1577
1578         if (ret)
1579                 printf("Passed tcondevtest\n");
1580
1581         return ret;
1582 }
1583
1584
1585 /*
1586   This test checks that 
1587
1588   1) the server supports multiple locking contexts on the one SMB
1589   connection, distinguished by PID.  
1590
1591   2) the server correctly fails overlapping locks made by the same PID (this
1592      goes against POSIX behaviour, which is why it is tricky to implement)
1593
1594   3) the server denies unlock requests by an incorrect client PID
1595 */
1596 static bool run_locktest2(int dummy)
1597 {
1598         static struct cli_state *cli;
1599         const char *fname = "\\lockt2.lck";
1600         uint16_t fnum1, fnum2, fnum3;
1601         bool correct = True;
1602         NTSTATUS status;
1603
1604         if (!torture_open_connection(&cli, 0)) {
1605                 return False;
1606         }
1607
1608         smbXcli_conn_set_sockopt(cli->conn, sockops);
1609
1610         printf("starting locktest2\n");
1611
1612         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1613
1614         cli_setpid(cli, 1);
1615
1616         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1617         if (!NT_STATUS_IS_OK(status)) {
1618                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1619                 return False;
1620         }
1621
1622         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1623         if (!NT_STATUS_IS_OK(status)) {
1624                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1625                 return False;
1626         }
1627
1628         cli_setpid(cli, 2);
1629
1630         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1631         if (!NT_STATUS_IS_OK(status)) {
1632                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1633                 return False;
1634         }
1635
1636         cli_setpid(cli, 1);
1637
1638         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1639         if (!NT_STATUS_IS_OK(status)) {
1640                 printf("lock1 failed (%s)\n", nt_errstr(status));
1641                 return false;
1642         }
1643
1644         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1645         if (NT_STATUS_IS_OK(status)) {
1646                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1647                 correct = false;
1648         } else {
1649                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1650                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1651                         return false;
1652                 }
1653         }
1654
1655         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1656         if (NT_STATUS_IS_OK(status)) {
1657                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1658                 correct = false;
1659         } else {
1660                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1661                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1662                         return false;
1663                 }
1664         }
1665
1666         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1667         if (NT_STATUS_IS_OK(status)) {
1668                 printf("READ lock2 succeeded! This is a locking bug\n");
1669                 correct = false;
1670         } else {
1671                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1672                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1673                         return false;
1674                 }
1675         }
1676
1677         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1678         if (!NT_STATUS_IS_OK(status)) {
1679                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1680         }
1681         cli_setpid(cli, 2);
1682         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1683                 printf("unlock at 100 succeeded! This is a locking bug\n");
1684                 correct = False;
1685         }
1686
1687         status = cli_unlock(cli, fnum1, 0, 4);
1688         if (NT_STATUS_IS_OK(status)) {
1689                 printf("unlock1 succeeded! This is a locking bug\n");
1690                 correct = false;
1691         } else {
1692                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1693                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1694                         return false;
1695                 }
1696         }
1697
1698         status = cli_unlock(cli, fnum1, 0, 8);
1699         if (NT_STATUS_IS_OK(status)) {
1700                 printf("unlock2 succeeded! This is a locking bug\n");
1701                 correct = false;
1702         } else {
1703                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1704                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1705                         return false;
1706                 }
1707         }
1708
1709         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1710         if (NT_STATUS_IS_OK(status)) {
1711                 printf("lock3 succeeded! This is a locking bug\n");
1712                 correct = false;
1713         } else {
1714                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1715                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1716                         return false;
1717                 }
1718         }
1719
1720         cli_setpid(cli, 1);
1721
1722         status = cli_close(cli, fnum1);
1723         if (!NT_STATUS_IS_OK(status)) {
1724                 printf("close1 failed (%s)\n", nt_errstr(status));
1725                 return False;
1726         }
1727
1728         status = cli_close(cli, fnum2);
1729         if (!NT_STATUS_IS_OK(status)) {
1730                 printf("close2 failed (%s)\n", nt_errstr(status));
1731                 return False;
1732         }
1733
1734         status = cli_close(cli, fnum3);
1735         if (!NT_STATUS_IS_OK(status)) {
1736                 printf("close3 failed (%s)\n", nt_errstr(status));
1737                 return False;
1738         }
1739
1740         if (!torture_close_connection(cli)) {
1741                 correct = False;
1742         }
1743
1744         printf("locktest2 finished\n");
1745
1746         return correct;
1747 }
1748
1749
1750 /*
1751   This test checks that 
1752
1753   1) the server supports the full offset range in lock requests
1754 */
1755 static bool run_locktest3(int dummy)
1756 {
1757         static struct cli_state *cli1, *cli2;
1758         const char *fname = "\\lockt3.lck";
1759         uint16_t fnum1, fnum2;
1760         int i;
1761         uint32_t offset;
1762         bool correct = True;
1763         NTSTATUS status;
1764
1765 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1766
1767         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1768                 return False;
1769         }
1770         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1771         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1772
1773         printf("starting locktest3\n");
1774
1775         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1776
1777         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1778                          &fnum1);
1779         if (!NT_STATUS_IS_OK(status)) {
1780                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1781                 return False;
1782         }
1783
1784         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1785         if (!NT_STATUS_IS_OK(status)) {
1786                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1787                 return False;
1788         }
1789
1790         for (offset=i=0;i<torture_numops;i++) {
1791                 NEXT_OFFSET;
1792
1793                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1794                 if (!NT_STATUS_IS_OK(status)) {
1795                         printf("lock1 %d failed (%s)\n", 
1796                                i,
1797                                nt_errstr(status));
1798                         return False;
1799                 }
1800
1801                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1802                 if (!NT_STATUS_IS_OK(status)) {
1803                         printf("lock2 %d failed (%s)\n", 
1804                                i,
1805                                nt_errstr(status));
1806                         return False;
1807                 }
1808         }
1809
1810         for (offset=i=0;i<torture_numops;i++) {
1811                 NEXT_OFFSET;
1812
1813                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1814                 if (NT_STATUS_IS_OK(status)) {
1815                         printf("error: lock1 %d succeeded!\n", i);
1816                         return False;
1817                 }
1818
1819                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1820                 if (NT_STATUS_IS_OK(status)) {
1821                         printf("error: lock2 %d succeeded!\n", i);
1822                         return False;
1823                 }
1824
1825                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1826                 if (NT_STATUS_IS_OK(status)) {
1827                         printf("error: lock3 %d succeeded!\n", i);
1828                         return False;
1829                 }
1830
1831                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1832                 if (NT_STATUS_IS_OK(status)) {
1833                         printf("error: lock4 %d succeeded!\n", i);
1834                         return False;
1835                 }
1836         }
1837
1838         for (offset=i=0;i<torture_numops;i++) {
1839                 NEXT_OFFSET;
1840
1841                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1842                 if (!NT_STATUS_IS_OK(status)) {
1843                         printf("unlock1 %d failed (%s)\n", 
1844                                i,
1845                                nt_errstr(status));
1846                         return False;
1847                 }
1848
1849                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1850                 if (!NT_STATUS_IS_OK(status)) {
1851                         printf("unlock2 %d failed (%s)\n", 
1852                                i,
1853                                nt_errstr(status));
1854                         return False;
1855                 }
1856         }
1857
1858         status = cli_close(cli1, fnum1);
1859         if (!NT_STATUS_IS_OK(status)) {
1860                 printf("close1 failed (%s)\n", nt_errstr(status));
1861                 return False;
1862         }
1863
1864         status = cli_close(cli2, fnum2);
1865         if (!NT_STATUS_IS_OK(status)) {
1866                 printf("close2 failed (%s)\n", nt_errstr(status));
1867                 return False;
1868         }
1869
1870         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1871         if (!NT_STATUS_IS_OK(status)) {
1872                 printf("unlink failed (%s)\n", nt_errstr(status));
1873                 return False;
1874         }
1875
1876         if (!torture_close_connection(cli1)) {
1877                 correct = False;
1878         }
1879
1880         if (!torture_close_connection(cli2)) {
1881                 correct = False;
1882         }
1883
1884         printf("finished locktest3\n");
1885
1886         return correct;
1887 }
1888
1889 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1890                            char *buf, off_t offset, size_t size,
1891                            size_t *nread, size_t expect)
1892 {
1893         NTSTATUS status;
1894         size_t l_nread;
1895
1896         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1897
1898         if(!NT_STATUS_IS_OK(status)) {
1899                 return false;
1900         } else if (l_nread != expect) {
1901                 return false;
1902         }
1903
1904         if (nread) {
1905                 *nread = l_nread;
1906         }
1907
1908         return true;
1909 }
1910
1911 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1912         printf("** "); correct = False; \
1913         }
1914
1915 /*
1916   looks at overlapping locks
1917 */
1918 static bool run_locktest4(int dummy)
1919 {
1920         static struct cli_state *cli1, *cli2;
1921         const char *fname = "\\lockt4.lck";
1922         uint16_t fnum1, fnum2, f;
1923         bool ret;
1924         char buf[1000];
1925         bool correct = True;
1926         NTSTATUS status;
1927
1928         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1929                 return False;
1930         }
1931
1932         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1933         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1934
1935         printf("starting locktest4\n");
1936
1937         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1938
1939         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1940         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1941
1942         memset(buf, 0, sizeof(buf));
1943
1944         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1945                               NULL);
1946         if (!NT_STATUS_IS_OK(status)) {
1947                 printf("Failed to create file: %s\n", nt_errstr(status));
1948                 correct = False;
1949                 goto fail;
1950         }
1951
1952         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1953               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1954         EXPECTED(ret, False);
1955         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1956
1957         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1958               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1959         EXPECTED(ret, True);
1960         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1961
1962         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1963               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1964         EXPECTED(ret, False);
1965         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1966
1967         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1968               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1969         EXPECTED(ret, True);
1970         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1971
1972         ret = (cli_setpid(cli1, 1),
1973               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1974               (cli_setpid(cli1, 2),
1975               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1976         EXPECTED(ret, False);
1977         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1978
1979         ret = (cli_setpid(cli1, 1),
1980               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1981               (cli_setpid(cli1, 2),
1982               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1983         EXPECTED(ret, True);
1984         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1985
1986         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1987               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1988         EXPECTED(ret, True);
1989         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1990
1991         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1992               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1993         EXPECTED(ret, False);
1994         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1995
1996         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1997               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1998         EXPECTED(ret, False);
1999         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2000
2001         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2002               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2003         EXPECTED(ret, True);
2004         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2005
2006         ret = (cli_setpid(cli1, 1),
2007              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2008              (cli_setpid(cli1, 2),
2009              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2010         EXPECTED(ret, False);
2011         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2012
2013         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2014               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2015               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2016         EXPECTED(ret, False);
2017         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2018
2019
2020         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2021               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2022         EXPECTED(ret, False);
2023         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2024
2025         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2026         ret = NT_STATUS_IS_OK(status);
2027         if (ret) {
2028                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2029                                       NULL);
2030                 ret = NT_STATUS_IS_OK(status);
2031         }
2032         EXPECTED(ret, False);
2033         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2034
2035
2036         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2037               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2038               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2039               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2040         EXPECTED(ret, True);
2041         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2042
2043
2044         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2045               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2046               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2047               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2048               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2049                                              150, 4, NULL))) &&
2050               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2051         EXPECTED(ret, True);
2052         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2053
2054         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2055               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2056               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2057                                            160, 4, NULL)) &&
2058               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2059         EXPECTED(ret, True);
2060         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2061
2062         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2063               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2064               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2065                                            170, 4, NULL)) &&
2066               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2067         EXPECTED(ret, True);
2068         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2069
2070         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2071               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2072               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2073               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2074                                             190, 4, NULL)) &&
2075               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2076         EXPECTED(ret, True);
2077         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2078
2079         cli_close(cli1, fnum1);
2080         cli_close(cli2, fnum2);
2081         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2082         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2083         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2084               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2085               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2086               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2087               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2088         cli_close(cli1, f);
2089         cli_close(cli1, fnum1);
2090         EXPECTED(ret, True);
2091         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2092
2093  fail:
2094         cli_close(cli1, fnum1);
2095         cli_close(cli2, fnum2);
2096         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2097         torture_close_connection(cli1);
2098         torture_close_connection(cli2);
2099
2100         printf("finished locktest4\n");
2101         return correct;
2102 }
2103
2104 /*
2105   looks at lock upgrade/downgrade.
2106 */
2107 static bool run_locktest5(int dummy)
2108 {
2109         static struct cli_state *cli1, *cli2;
2110         const char *fname = "\\lockt5.lck";
2111         uint16_t fnum1, fnum2, fnum3;
2112         bool ret;
2113         char buf[1000];
2114         bool correct = True;
2115         NTSTATUS status;
2116
2117         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2118                 return False;
2119         }
2120
2121         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2122         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2123
2124         printf("starting locktest5\n");
2125
2126         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2127
2128         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2129         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2130         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2131
2132         memset(buf, 0, sizeof(buf));
2133
2134         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2135                               NULL);
2136         if (!NT_STATUS_IS_OK(status)) {
2137                 printf("Failed to create file: %s\n", nt_errstr(status));
2138                 correct = False;
2139                 goto fail;
2140         }
2141
2142         /* Check for NT bug... */
2143         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2144               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2145         cli_close(cli1, fnum1);
2146         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2147         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2148         ret = NT_STATUS_IS_OK(status);
2149         EXPECTED(ret, True);
2150         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2151         cli_close(cli1, fnum1);
2152         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2153         cli_unlock(cli1, fnum3, 0, 1);
2154
2155         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2156               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2157         EXPECTED(ret, True);
2158         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2159
2160         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2161         ret = NT_STATUS_IS_OK(status);
2162         EXPECTED(ret, False);
2163
2164         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2165
2166         /* Unlock the process 2 lock. */
2167         cli_unlock(cli2, fnum2, 0, 4);
2168
2169         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2170         ret = NT_STATUS_IS_OK(status);
2171         EXPECTED(ret, False);
2172
2173         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2174
2175         /* Unlock the process 1 fnum3 lock. */
2176         cli_unlock(cli1, fnum3, 0, 4);
2177
2178         /* Stack 2 more locks here. */
2179         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2180               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2181
2182         EXPECTED(ret, True);
2183         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2184
2185         /* Unlock the first process lock, then check this was the WRITE lock that was
2186                 removed. */
2187
2188         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2189               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2190
2191         EXPECTED(ret, True);
2192         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2193
2194         /* Unlock the process 2 lock. */
2195         cli_unlock(cli2, fnum2, 0, 4);
2196
2197         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2198
2199         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2200                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2201                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2202
2203         EXPECTED(ret, True);
2204         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2205
2206         /* Ensure the next unlock fails. */
2207         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2208         EXPECTED(ret, False);
2209         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2210
2211         /* Ensure connection 2 can get a write lock. */
2212         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2213         ret = NT_STATUS_IS_OK(status);
2214         EXPECTED(ret, True);
2215
2216         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2217
2218
2219  fail:
2220         cli_close(cli1, fnum1);
2221         cli_close(cli2, fnum2);
2222         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2223         if (!torture_close_connection(cli1)) {
2224                 correct = False;
2225         }
2226         if (!torture_close_connection(cli2)) {
2227                 correct = False;
2228         }
2229
2230         printf("finished locktest5\n");
2231
2232         return correct;
2233 }
2234
2235 /*
2236   tries the unusual lockingX locktype bits
2237 */
2238 static bool run_locktest6(int dummy)
2239 {
2240         static struct cli_state *cli;
2241         const char *fname[1] = { "\\lock6.txt" };
2242         int i;
2243         uint16_t fnum;
2244         NTSTATUS status;
2245
2246         if (!torture_open_connection(&cli, 0)) {
2247                 return False;
2248         }
2249
2250         smbXcli_conn_set_sockopt(cli->conn, sockops);
2251
2252         printf("starting locktest6\n");
2253
2254         for (i=0;i<1;i++) {
2255                 printf("Testing %s\n", fname[i]);
2256
2257                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2258
2259                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2260                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2261                 cli_close(cli, fnum);
2262                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2263
2264                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2265                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2266                 cli_close(cli, fnum);
2267                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2268
2269                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2270         }
2271
2272         torture_close_connection(cli);
2273
2274         printf("finished locktest6\n");
2275         return True;
2276 }
2277
2278 static bool run_locktest7(int dummy)
2279 {
2280         struct cli_state *cli1;
2281         const char *fname = "\\lockt7.lck";
2282         uint16_t fnum1;
2283         char buf[200];
2284         bool correct = False;
2285         size_t nread;
2286         NTSTATUS status;
2287
2288         if (!torture_open_connection(&cli1, 0)) {
2289                 return False;
2290         }
2291
2292         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2293
2294         printf("starting locktest7\n");
2295
2296         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2297
2298         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2299
2300         memset(buf, 0, sizeof(buf));
2301
2302         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2303                               NULL);
2304         if (!NT_STATUS_IS_OK(status)) {
2305                 printf("Failed to create file: %s\n", nt_errstr(status));
2306                 goto fail;
2307         }
2308
2309         cli_setpid(cli1, 1);
2310
2311         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2312         if (!NT_STATUS_IS_OK(status)) {
2313                 printf("Unable to apply read lock on range 130:4, "
2314                        "error was %s\n", nt_errstr(status));
2315                 goto fail;
2316         } else {
2317                 printf("pid1 successfully locked range 130:4 for READ\n");
2318         }
2319
2320         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2321         if (!NT_STATUS_IS_OK(status)) {
2322                 printf("pid1 unable to read the range 130:4, error was %s\n",
2323                       nt_errstr(status));
2324                 goto fail;
2325         } else if (nread != 4) {
2326                 printf("pid1 unable to read the range 130:4, "
2327                        "recv %ld req %d\n", (unsigned long)nread, 4);
2328                 goto fail;
2329         } else {
2330                 printf("pid1 successfully read the range 130:4\n");
2331         }
2332
2333         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2334         if (!NT_STATUS_IS_OK(status)) {
2335                 printf("pid1 unable to write to the range 130:4, error was "
2336                        "%s\n", nt_errstr(status));
2337                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2338                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2339                         goto fail;
2340                 }
2341         } else {
2342                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2343                 goto fail;
2344         }
2345
2346         cli_setpid(cli1, 2);
2347
2348         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2349         if (!NT_STATUS_IS_OK(status)) {
2350                 printf("pid2 unable to read the range 130:4, error was %s\n",
2351                       nt_errstr(status));
2352                 goto fail;
2353         } else if (nread != 4) {
2354                 printf("pid2 unable to read the range 130:4, "
2355                        "recv %ld req %d\n", (unsigned long)nread, 4);
2356                 goto fail;
2357         } else {
2358                 printf("pid2 successfully read the range 130:4\n");
2359         }
2360
2361         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2362         if (!NT_STATUS_IS_OK(status)) {
2363                 printf("pid2 unable to write to the range 130:4, error was "
2364                        "%s\n", nt_errstr(status));
2365                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2366                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2367                         goto fail;
2368                 }
2369         } else {
2370                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2371                 goto fail;
2372         }
2373
2374         cli_setpid(cli1, 1);
2375         cli_unlock(cli1, fnum1, 130, 4);
2376
2377         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2378         if (!NT_STATUS_IS_OK(status)) {
2379                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2380                 goto fail;
2381         } else {
2382                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2383         }
2384
2385         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2386         if (!NT_STATUS_IS_OK(status)) {
2387                 printf("pid1 unable to read the range 130:4, error was %s\n",
2388                       nt_errstr(status));
2389                 goto fail;
2390         } else if (nread != 4) {
2391                 printf("pid1 unable to read the range 130:4, "
2392                        "recv %ld req %d\n", (unsigned long)nread, 4);
2393                 goto fail;
2394         } else {
2395                 printf("pid1 successfully read the range 130:4\n");
2396         }
2397
2398         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2399         if (!NT_STATUS_IS_OK(status)) {
2400                 printf("pid1 unable to write to the range 130:4, error was "
2401                        "%s\n", nt_errstr(status));
2402                 goto fail;
2403         } else {
2404                 printf("pid1 successfully wrote to the range 130:4\n");
2405         }
2406
2407         cli_setpid(cli1, 2);
2408
2409         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 printf("pid2 unable to read the range 130:4, error was "
2412                        "%s\n", nt_errstr(status));
2413                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2414                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2415                         goto fail;
2416                 }
2417         } else {
2418                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2419                        (unsigned long)nread);
2420                 goto fail;
2421         }
2422
2423         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2424         if (!NT_STATUS_IS_OK(status)) {
2425                 printf("pid2 unable to write to the range 130:4, error was "
2426                        "%s\n", nt_errstr(status));
2427                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2428                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2429                         goto fail;
2430                 }
2431         } else {
2432                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2433                 goto fail;
2434         }
2435
2436         cli_unlock(cli1, fnum1, 130, 0);
2437         correct = True;
2438
2439 fail:
2440         cli_close(cli1, fnum1);
2441         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2442         torture_close_connection(cli1);
2443
2444         printf("finished locktest7\n");
2445         return correct;
2446 }
2447
2448 /*
2449  * This demonstrates a problem with our use of GPFS share modes: A file
2450  * descriptor sitting in the pending close queue holding a GPFS share mode
2451  * blocks opening a file another time. Happens with Word 2007 temp files.
2452  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2453  * open is denied with NT_STATUS_SHARING_VIOLATION.
2454  */
2455
2456 static bool run_locktest8(int dummy)
2457 {
2458         struct cli_state *cli1;
2459         const char *fname = "\\lockt8.lck";
2460         uint16_t fnum1, fnum2;
2461         char buf[200];
2462         bool correct = False;
2463         NTSTATUS status;
2464
2465         if (!torture_open_connection(&cli1, 0)) {
2466                 return False;
2467         }
2468
2469         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2470
2471         printf("starting locktest8\n");
2472
2473         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2474
2475         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2476                           &fnum1);
2477         if (!NT_STATUS_IS_OK(status)) {
2478                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2479                 return false;
2480         }
2481
2482         memset(buf, 0, sizeof(buf));
2483
2484         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2485         if (!NT_STATUS_IS_OK(status)) {
2486                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2487                           nt_errstr(status));
2488                 goto fail;
2489         }
2490
2491         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 printf("Unable to apply read lock on range 1:1, error was "
2494                        "%s\n", nt_errstr(status));
2495                 goto fail;
2496         }
2497
2498         status = cli_close(cli1, fnum1);
2499         if (!NT_STATUS_IS_OK(status)) {
2500                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2501                 goto fail;
2502         }
2503
2504         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2505         if (!NT_STATUS_IS_OK(status)) {
2506                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2507                           nt_errstr(status));
2508                 goto fail;
2509         }
2510
2511         correct = true;
2512
2513 fail:
2514         cli_close(cli1, fnum1);
2515         cli_close(cli1, fnum2);
2516         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2517         torture_close_connection(cli1);
2518
2519         printf("finished locktest8\n");
2520         return correct;
2521 }
2522
2523 /*
2524  * This test is designed to be run in conjunction with
2525  * external NFS or POSIX locks taken in the filesystem.
2526  * It checks that the smbd server will block until the
2527  * lock is released and then acquire it. JRA.
2528  */
2529
2530 static bool got_alarm;
2531 static struct cli_state *alarm_cli;
2532
2533 static void alarm_handler(int dummy)
2534 {
2535         got_alarm = True;
2536 }
2537
2538 static void alarm_handler_parent(int dummy)
2539 {
2540         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2541 }
2542
2543 static void do_local_lock(int read_fd, int write_fd)
2544 {
2545         int fd;
2546         char c = '\0';
2547         struct flock lock;
2548         const char *local_pathname = NULL;
2549         int ret;
2550
2551         local_pathname = talloc_asprintf(talloc_tos(),
2552                         "%s/lockt9.lck", local_path);
2553         if (!local_pathname) {
2554                 printf("child: alloc fail\n");
2555                 exit(1);
2556         }
2557
2558         unlink(local_pathname);
2559         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2560         if (fd == -1) {
2561                 printf("child: open of %s failed %s.\n",
2562                         local_pathname, strerror(errno));
2563                 exit(1);
2564         }
2565
2566         /* Now take a fcntl lock. */
2567         lock.l_type = F_WRLCK;
2568         lock.l_whence = SEEK_SET;
2569         lock.l_start = 0;
2570         lock.l_len = 4;
2571         lock.l_pid = getpid();
2572
2573         ret = fcntl(fd,F_SETLK,&lock);
2574         if (ret == -1) {
2575                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2576                         local_pathname, strerror(errno));
2577                 exit(1);
2578         } else {
2579                 printf("child: got lock 0:4 on file %s.\n",
2580                         local_pathname );
2581                 fflush(stdout);
2582         }
2583
2584         CatchSignal(SIGALRM, alarm_handler);
2585         alarm(5);
2586         /* Signal the parent. */
2587         if (write(write_fd, &c, 1) != 1) {
2588                 printf("child: start signal fail %s.\n",
2589                         strerror(errno));
2590                 exit(1);
2591         }
2592         alarm(0);
2593
2594         alarm(10);
2595         /* Wait for the parent to be ready. */
2596         if (read(read_fd, &c, 1) != 1) {
2597                 printf("child: reply signal fail %s.\n",
2598                         strerror(errno));
2599                 exit(1);
2600         }
2601         alarm(0);
2602
2603         sleep(5);
2604         close(fd);
2605         printf("child: released lock 0:4 on file %s.\n",
2606                 local_pathname );
2607         fflush(stdout);
2608         exit(0);
2609 }
2610
2611 static bool run_locktest9(int dummy)
2612 {
2613         struct cli_state *cli1;
2614         const char *fname = "\\lockt9.lck";
2615         uint16_t fnum;
2616         bool correct = False;
2617         int pipe_in[2], pipe_out[2];
2618         pid_t child_pid;
2619         char c = '\0';
2620         int ret;
2621         struct timeval start;
2622         double seconds;
2623         NTSTATUS status;
2624
2625         printf("starting locktest9\n");
2626
2627         if (local_path == NULL) {
2628                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2629                 return false;
2630         }
2631
2632         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2633                 return false;
2634         }
2635
2636         child_pid = fork();
2637         if (child_pid == -1) {
2638                 return false;
2639         }
2640
2641         if (child_pid == 0) {
2642                 /* Child. */
2643                 do_local_lock(pipe_out[0], pipe_in[1]);
2644                 exit(0);
2645         }
2646
2647         close(pipe_out[0]);
2648         close(pipe_in[1]);
2649         pipe_out[0] = -1;
2650         pipe_in[1] = -1;
2651
2652         /* Parent. */
2653         ret = read(pipe_in[0], &c, 1);
2654         if (ret != 1) {
2655                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2656                         strerror(errno));
2657                 return false;
2658         }
2659
2660         if (!torture_open_connection(&cli1, 0)) {
2661                 return false;
2662         }
2663
2664         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2665
2666         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2667                           &fnum);
2668         if (!NT_STATUS_IS_OK(status)) {
2669                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2670                 return false;
2671         }
2672
2673         /* Ensure the child has the lock. */
2674         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2675         if (NT_STATUS_IS_OK(status)) {
2676                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2677                 goto fail;
2678         } else {
2679                 d_printf("Child has the lock.\n");
2680         }
2681
2682         /* Tell the child to wait 5 seconds then exit. */
2683         ret = write(pipe_out[1], &c, 1);
2684         if (ret != 1) {
2685                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2686                         strerror(errno));
2687                 goto fail;
2688         }
2689
2690         /* Wait 20 seconds for the lock. */
2691         alarm_cli = cli1;
2692         CatchSignal(SIGALRM, alarm_handler_parent);
2693         alarm(20);
2694
2695         start = timeval_current();
2696
2697         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2698         if (!NT_STATUS_IS_OK(status)) {
2699                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2700                        "%s\n", nt_errstr(status));
2701                 goto fail_nofd;
2702         }
2703         alarm(0);
2704
2705         seconds = timeval_elapsed(&start);
2706
2707         printf("Parent got the lock after %.2f seconds.\n",
2708                 seconds);
2709
2710         status = cli_close(cli1, fnum);
2711         if (!NT_STATUS_IS_OK(status)) {
2712                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2713                 goto fail;
2714         }
2715
2716         correct = true;
2717
2718 fail:
2719         cli_close(cli1, fnum);
2720         torture_close_connection(cli1);
2721
2722 fail_nofd:
2723
2724         printf("finished locktest9\n");
2725         return correct;
2726 }
2727
2728 /*
2729 test whether fnums and tids open on one VC are available on another (a major
2730 security hole)
2731 */
2732 static bool run_fdpasstest(int dummy)
2733 {
2734         struct cli_state *cli1, *cli2;
2735         const char *fname = "\\fdpass.tst";
2736         uint16_t fnum1;
2737         char buf[1024];
2738         NTSTATUS status;
2739
2740         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2741                 return False;
2742         }
2743         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2744         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2745
2746         printf("starting fdpasstest\n");
2747
2748         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2749
2750         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2751                           &fnum1);
2752         if (!NT_STATUS_IS_OK(status)) {
2753                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2754                 return False;
2755         }
2756
2757         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2758                               13, NULL);
2759         if (!NT_STATUS_IS_OK(status)) {
2760                 printf("write failed (%s)\n", nt_errstr(status));
2761                 return False;
2762         }
2763
2764         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2765         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2766         cli_setpid(cli2, cli_getpid(cli1));
2767
2768         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2769                 printf("read succeeded! nasty security hole [%s]\n", buf);
2770                 return false;
2771         }
2772
2773         cli_close(cli1, fnum1);
2774         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2775
2776         torture_close_connection(cli1);
2777         torture_close_connection(cli2);
2778
2779         printf("finished fdpasstest\n");
2780         return True;
2781 }
2782
2783 static bool run_fdsesstest(int dummy)
2784 {
2785         struct cli_state *cli;
2786         uint16_t new_vuid;
2787         uint16_t saved_vuid;
2788         uint32_t new_cnum;
2789         uint32_t saved_cnum;
2790         const char *fname = "\\fdsess.tst";
2791         const char *fname1 = "\\fdsess1.tst";
2792         uint16_t fnum1;
2793         uint16_t fnum2;
2794         char buf[1024];
2795         bool ret = True;
2796         NTSTATUS status;
2797
2798         if (!torture_open_connection(&cli, 0))
2799                 return False;
2800         smbXcli_conn_set_sockopt(cli->conn, sockops);
2801
2802         if (!torture_cli_session_setup2(cli, &new_vuid))
2803                 return False;
2804
2805         saved_cnum = cli_state_get_tid(cli);
2806         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2807                 return False;
2808         new_cnum = cli_state_get_tid(cli);
2809         cli_state_set_tid(cli, saved_cnum);
2810
2811         printf("starting fdsesstest\n");
2812
2813         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2814         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2815
2816         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2817         if (!NT_STATUS_IS_OK(status)) {
2818                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2819                 return False;
2820         }
2821
2822         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2823                               NULL);
2824         if (!NT_STATUS_IS_OK(status)) {
2825                 printf("write failed (%s)\n", nt_errstr(status));
2826                 return False;
2827         }
2828
2829         saved_vuid = cli_state_get_uid(cli);
2830         cli_state_set_uid(cli, new_vuid);
2831
2832         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2833                 printf("read succeeded with different vuid! "
2834                        "nasty security hole [%s]\n", buf);
2835                 ret = false;
2836         }
2837         /* Try to open a file with different vuid, samba cnum. */
2838         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2839                 printf("create with different vuid, same cnum succeeded.\n");
2840                 cli_close(cli, fnum2);
2841                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2842         } else {
2843                 printf("create with different vuid, same cnum failed.\n");
2844                 printf("This will cause problems with service clients.\n");
2845                 ret = False;
2846         }
2847
2848         cli_state_set_uid(cli, saved_vuid);
2849
2850         /* Try with same vuid, different cnum. */
2851         cli_state_set_tid(cli, new_cnum);
2852
2853         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2854                 printf("read succeeded with different cnum![%s]\n", buf);
2855                 ret = false;
2856         }
2857
2858         cli_state_set_tid(cli, saved_cnum);
2859         cli_close(cli, fnum1);
2860         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2861
2862         torture_close_connection(cli);
2863
2864         printf("finished fdsesstest\n");
2865         return ret;
2866 }
2867
2868 /*
2869   This test checks that 
2870
2871   1) the server does not allow an unlink on a file that is open
2872 */
2873 static bool run_unlinktest(int dummy)
2874 {
2875         struct cli_state *cli;
2876         const char *fname = "\\unlink.tst";
2877         uint16_t fnum;
2878         bool correct = True;
2879         NTSTATUS status;
2880
2881         if (!torture_open_connection(&cli, 0)) {
2882                 return False;
2883         }
2884
2885         smbXcli_conn_set_sockopt(cli->conn, sockops);
2886
2887         printf("starting unlink test\n");
2888
2889         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2890
2891         cli_setpid(cli, 1);
2892
2893         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2894         if (!NT_STATUS_IS_OK(status)) {
2895                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2896                 return False;
2897         }
2898
2899         status = cli_unlink(cli, fname,
2900                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2901         if (NT_STATUS_IS_OK(status)) {
2902                 printf("error: server allowed unlink on an open file\n");
2903                 correct = False;
2904         } else {
2905                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2906                                       NT_STATUS_SHARING_VIOLATION);
2907         }
2908
2909         cli_close(cli, fnum);
2910         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2911
2912         if (!torture_close_connection(cli)) {
2913                 correct = False;
2914         }
2915
2916         printf("unlink test finished\n");
2917
2918         return correct;
2919 }
2920
2921
2922 /*
2923 test how many open files this server supports on the one socket
2924 */
2925 static bool run_maxfidtest(int dummy)
2926 {
2927         struct cli_state *cli;
2928         fstring fname;
2929         uint16_t fnums[0x11000];
2930         int i;
2931         int retries=4;
2932         bool correct = True;
2933         NTSTATUS status;
2934
2935         cli = current_cli;
2936
2937         if (retries <= 0) {
2938                 printf("failed to connect\n");
2939                 return False;
2940         }
2941
2942         smbXcli_conn_set_sockopt(cli->conn, sockops);
2943
2944         for (i=0; i<0x11000; i++) {
2945                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2946                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2947                                   &fnums[i]);
2948                 if (!NT_STATUS_IS_OK(status)) {
2949                         printf("open of %s failed (%s)\n", 
2950                                fname, nt_errstr(status));
2951                         printf("maximum fnum is %d\n", i);
2952                         break;
2953                 }
2954                 printf("%6d\r", i);
2955         }
2956         printf("%6d\n", i);
2957         i--;
2958
2959         printf("cleaning up\n");
2960         for (;i>=0;i--) {
2961                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2962                 cli_close(cli, fnums[i]);
2963
2964                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2965                 if (!NT_STATUS_IS_OK(status)) {
2966                         printf("unlink of %s failed (%s)\n", 
2967                                fname, nt_errstr(status));
2968                         correct = False;
2969                 }
2970                 printf("%6d\r", i);
2971         }
2972         printf("%6d\n", 0);
2973
2974         printf("maxfid test finished\n");
2975         if (!torture_close_connection(cli)) {
2976                 correct = False;
2977         }
2978         return correct;
2979 }
2980
2981 /* generate a random buffer */
2982 static void rand_buf(char *buf, int len)
2983 {
2984         while (len--) {
2985                 *buf = (char)sys_random();
2986                 buf++;
2987         }
2988 }
2989
2990 /* send smb negprot commands, not reading the response */
2991 static bool run_negprot_nowait(int dummy)
2992 {
2993         struct tevent_context *ev;
2994         int i;
2995         struct cli_state *cli;
2996         bool correct = True;
2997
2998         printf("starting negprot nowait test\n");
2999
3000         ev = samba_tevent_context_init(talloc_tos());
3001         if (ev == NULL) {
3002                 return false;
3003         }
3004
3005         if (!(cli = open_nbt_connection())) {
3006                 TALLOC_FREE(ev);
3007                 return False;
3008         }
3009
3010         for (i=0;i<50000;i++) {
3011                 struct tevent_req *req;
3012
3013                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3014                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3015                 if (req == NULL) {
3016                         TALLOC_FREE(ev);
3017                         return false;
3018                 }
3019                 if (!tevent_req_poll(req, ev)) {
3020                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3021                                   strerror(errno));
3022                         TALLOC_FREE(ev);
3023                         return false;
3024                 }
3025                 TALLOC_FREE(req);
3026         }
3027
3028         if (torture_close_connection(cli)) {
3029                 correct = False;
3030         }
3031
3032         printf("finished negprot nowait test\n");
3033
3034         return correct;
3035 }
3036
3037 /* send smb negprot commands, not reading the response */
3038 static bool run_bad_nbt_session(int dummy)
3039 {
3040         struct nmb_name called, calling;
3041         struct sockaddr_storage ss;
3042         NTSTATUS status;
3043         int fd;
3044         bool ret;
3045
3046         printf("starting bad nbt session test\n");
3047
3048         make_nmb_name(&calling, myname, 0x0);
3049         make_nmb_name(&called , host, 0x20);
3050
3051         if (!resolve_name(host, &ss, 0x20, true)) {
3052                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3053                 return false;
3054         }
3055
3056         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3057         if (!NT_STATUS_IS_OK(status)) {
3058                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3059                           nt_errstr(status));
3060                 return false;
3061         }
3062
3063         ret = cli_bad_session_request(fd, &calling, &called);
3064         close(fd);
3065         if (!ret) {
3066                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3067                           nt_errstr(status));
3068                 return false;
3069         }
3070
3071         printf("finished bad nbt session test\n");
3072         return true;
3073 }
3074
3075 /* send random IPC commands */
3076 static bool run_randomipc(int dummy)
3077 {
3078         char *rparam = NULL;
3079         char *rdata = NULL;
3080         unsigned int rdrcnt,rprcnt;
3081         char param[1024];
3082         int api, param_len, i;
3083         struct cli_state *cli;
3084         bool correct = True;
3085         int count = 50000;
3086
3087         printf("starting random ipc test\n");
3088
3089         if (!torture_open_connection(&cli, 0)) {
3090                 return False;
3091         }
3092
3093         for (i=0;i<count;i++) {
3094                 api = sys_random() % 500;
3095                 param_len = (sys_random() % 64);
3096
3097                 rand_buf(param, param_len);
3098
3099                 SSVAL(param,0,api); 
3100
3101                 cli_api(cli, 
3102                         param, param_len, 8,  
3103                         NULL, 0, CLI_BUFFER_SIZE,
3104                         &rparam, &rprcnt,     
3105                         &rdata, &rdrcnt);
3106                 if (i % 100 == 0) {
3107                         printf("%d/%d\r", i,count);
3108                 }
3109         }
3110         printf("%d/%d\n", i, count);
3111
3112         if (!torture_close_connection(cli)) {
3113                 correct = False;
3114         }
3115
3116         SAFE_FREE(rparam);
3117         SAFE_FREE(rdata);
3118
3119         printf("finished random ipc test\n");
3120
3121         return correct;
3122 }
3123
3124
3125
3126 static void browse_callback(const char *sname, uint32_t stype,
3127                             const char *comment, void *state)
3128 {
3129         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3130 }
3131
3132
3133
3134 /*
3135   This test checks the browse list code
3136
3137 */
3138 static bool run_browsetest(int dummy)
3139 {
3140         static struct cli_state *cli;
3141         bool correct = True;
3142
3143         printf("starting browse test\n");
3144
3145         if (!torture_open_connection(&cli, 0)) {
3146                 return False;
3147         }
3148
3149         printf("domain list:\n");
3150         cli_NetServerEnum(cli, cli->server_domain, 
3151                           SV_TYPE_DOMAIN_ENUM,
3152                           browse_callback, NULL);
3153
3154         printf("machine list:\n");
3155         cli_NetServerEnum(cli, cli->server_domain, 
3156                           SV_TYPE_ALL,
3157                           browse_callback, NULL);
3158
3159         if (!torture_close_connection(cli)) {
3160                 correct = False;
3161         }
3162
3163         printf("browse test finished\n");
3164
3165         return correct;
3166
3167 }
3168
3169 static bool check_attributes(struct cli_state *cli,
3170                                 const char *fname,
3171                                 uint16_t expected_attrs)
3172 {
3173         uint16_t attrs = 0;
3174         NTSTATUS status = cli_getatr(cli,
3175                                 fname,
3176                                 &attrs,
3177                                 NULL,
3178                                 NULL);
3179         if (!NT_STATUS_IS_OK(status)) {
3180                 printf("cli_getatr failed with %s\n",
3181                         nt_errstr(status));
3182                 return false;
3183         }
3184         if (attrs != expected_attrs) {
3185                 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3186                         (unsigned int)attrs,
3187                         (unsigned int)expected_attrs);
3188                 return false;
3189         }
3190         return true;
3191 }
3192
3193 /*
3194   This checks how the getatr calls works
3195 */
3196 static bool run_attrtest(int dummy)
3197 {
3198         struct cli_state *cli;
3199         uint16_t fnum;
3200         time_t t, t2;
3201         const char *fname = "\\attrib123456789.tst";
3202         bool correct = True;
3203         NTSTATUS status;
3204
3205         printf("starting attrib test\n");
3206
3207         if (!torture_open_connection(&cli, 0)) {
3208                 return False;
3209         }
3210
3211         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3212         cli_openx(cli, fname, 
3213                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3214         cli_close(cli, fnum);
3215
3216         status = cli_getatr(cli, fname, NULL, NULL, &t);
3217         if (!NT_STATUS_IS_OK(status)) {
3218                 printf("getatr failed (%s)\n", nt_errstr(status));
3219                 correct = False;
3220         }
3221
3222         if (labs(t - time(NULL)) > 60*60*24*10) {
3223                 printf("ERROR: SMBgetatr bug. time is %s",
3224                        ctime(&t));
3225                 t = time(NULL);
3226                 correct = True;
3227         }
3228
3229         t2 = t-60*60*24; /* 1 day ago */
3230
3231         status = cli_setatr(cli, fname, 0, t2);
3232         if (!NT_STATUS_IS_OK(status)) {
3233                 printf("setatr failed (%s)\n", nt_errstr(status));
3234                 correct = True;
3235         }
3236
3237         status = cli_getatr(cli, fname, NULL, NULL, &t);
3238         if (!NT_STATUS_IS_OK(status)) {
3239                 printf("getatr failed (%s)\n", nt_errstr(status));
3240                 correct = True;
3241         }
3242
3243         if (t != t2) {
3244                 printf("ERROR: getatr/setatr bug. times are\n%s",
3245                        ctime(&t));
3246                 printf("%s", ctime(&t2));
3247                 correct = True;
3248         }
3249
3250         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3251
3252         /* Check cli_setpathinfo_basic() */
3253         /* Re-create the file. */
3254         status = cli_openx(cli, fname,
3255                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3256         if (!NT_STATUS_IS_OK(status)) {
3257                 printf("Failed to recreate %s (%s)\n",
3258                         fname, nt_errstr(status));
3259                 correct = false;
3260         }
3261         cli_close(cli, fnum);
3262
3263         status = cli_setpathinfo_basic(cli,
3264                                         fname,
3265                                         0, /* create */
3266                                         0, /* access */
3267                                         0, /* write */
3268                                         0, /* change */
3269                                         FILE_ATTRIBUTE_SYSTEM |
3270                                         FILE_ATTRIBUTE_HIDDEN |
3271                                         FILE_ATTRIBUTE_READONLY);
3272         if (!NT_STATUS_IS_OK(status)) {
3273                 printf("cli_setpathinfo_basic failed with %s\n",
3274                         nt_errstr(status));
3275                 correct = false;
3276         }
3277
3278         /* Check attributes are correct. */
3279         correct = check_attributes(cli,
3280                         fname,
3281                         FILE_ATTRIBUTE_SYSTEM |
3282                         FILE_ATTRIBUTE_HIDDEN |
3283                         FILE_ATTRIBUTE_READONLY);
3284         if (correct == false) {
3285                 goto out;
3286         }
3287
3288         /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
3289         status = cli_setpathinfo_basic(cli,
3290                                         fname,
3291                                         0, /* create */
3292                                         0, /* access */
3293                                         0, /* write */
3294                                         0, /* change */
3295                                         FILE_ATTRIBUTE_NORMAL);
3296         if (!NT_STATUS_IS_OK(status)) {
3297                 printf("cli_setpathinfo_basic failed with %s\n",
3298                         nt_errstr(status));
3299                 correct = false;
3300         }
3301
3302         /* Check attributes are correct. */
3303         correct = check_attributes(cli,
3304                         fname,
3305                         FILE_ATTRIBUTE_SYSTEM |
3306                         FILE_ATTRIBUTE_HIDDEN |
3307                         FILE_ATTRIBUTE_READONLY);
3308         if (correct == false) {
3309                 goto out;
3310         }
3311
3312         /* Setting to (uint16_t)-1 should also be ignored. */
3313         status = cli_setpathinfo_basic(cli,
3314                                         fname,
3315                                         0, /* create */
3316                                         0, /* access */
3317                                         0, /* write */
3318                                         0, /* change */
3319                                         (uint16_t)-1);
3320         if (!NT_STATUS_IS_OK(status)) {
3321                 printf("cli_setpathinfo_basic failed with %s\n",
3322                         nt_errstr(status));
3323                 correct = false;
3324         }
3325
3326         /* Check attributes are correct. */
3327         correct = check_attributes(cli,
3328                         fname,
3329                         FILE_ATTRIBUTE_SYSTEM |
3330                         FILE_ATTRIBUTE_HIDDEN |
3331                         FILE_ATTRIBUTE_READONLY);
3332         if (correct == false) {
3333                 goto out;
3334         }
3335
3336         /* Setting to 0 should clear them all. */
3337         status = cli_setpathinfo_basic(cli,
3338                                         fname,
3339                                         0, /* create */
3340                                         0, /* access */
3341                                         0, /* write */
3342                                         0, /* change */
3343                                         0);
3344         if (!NT_STATUS_IS_OK(status)) {
3345                 printf("cli_setpathinfo_basic failed with %s\n",
3346                         nt_errstr(status));
3347                 correct = false;
3348         }
3349
3350         /* Check attributes are correct. */
3351         correct = check_attributes(cli,
3352                         fname,
3353                         FILE_ATTRIBUTE_NORMAL);
3354         if (correct == false) {
3355                 goto out;
3356         }
3357
3358   out:
3359
3360         cli_unlink(cli,
3361                 fname,
3362                 FILE_ATTRIBUTE_SYSTEM |
3363                 FILE_ATTRIBUTE_HIDDEN|
3364                 FILE_ATTRIBUTE_READONLY);
3365
3366         if (!torture_close_connection(cli)) {
3367                 correct = False;
3368         }
3369
3370         printf("attrib test finished\n");
3371
3372         return correct;
3373 }
3374
3375
3376 /*
3377   This checks a couple of trans2 calls
3378 */
3379 static bool run_trans2test(int dummy)
3380 {
3381         struct cli_state *cli;
3382         uint16_t fnum;
3383         off_t size;
3384         time_t c_time, a_time, m_time;
3385         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3386         const char *fname = "\\trans2.tst";
3387         const char *dname = "\\trans2";
3388         const char *fname2 = "\\trans2\\trans2.tst";
3389         char *pname;
3390         bool correct = True;
3391         NTSTATUS status;
3392         uint32_t fs_attr;
3393
3394         printf("starting trans2 test\n");
3395
3396         if (!torture_open_connection(&cli, 0)) {
3397                 return False;
3398         }
3399
3400         status = cli_get_fs_attr_info(cli, &fs_attr);
3401         if (!NT_STATUS_IS_OK(status)) {
3402                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3403                        nt_errstr(status));
3404                 correct = false;
3405         }
3406
3407         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3408         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3409         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3410                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3411         if (!NT_STATUS_IS_OK(status)) {
3412                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3413                 correct = False;
3414         }
3415
3416         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3417         if (!NT_STATUS_IS_OK(status)) {
3418                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3419                 correct = False;
3420         }
3421         else if (strcmp(pname, fname)) {
3422                 printf("qfilename gave different name? [%s] [%s]\n",
3423                        fname, pname);
3424                 correct = False;
3425         }
3426
3427         cli_close(cli, fnum);
3428
3429         sleep(2);
3430
3431         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3432         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3433                           &fnum);
3434         if (!NT_STATUS_IS_OK(status)) {
3435                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3436                 return False;
3437         }
3438         cli_close(cli, fnum);
3439
3440         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3441                                 NULL);
3442         if (!NT_STATUS_IS_OK(status)) {
3443                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3444                 correct = False;
3445         } else {
3446                 time_t t = time(NULL);
3447
3448                 if (c_time != m_time) {
3449                         printf("create time=%s", ctime(&c_time));
3450                         printf("modify time=%s", ctime(&m_time));
3451                         printf("This system appears to have sticky create times\n");
3452                 }
3453                 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3454                         printf("access time=%s", ctime(&a_time));
3455                         printf("This system appears to set a midnight access time\n");
3456                         correct = False;
3457                 }
3458
3459                 if (labs(m_time - t) > 60*60*24*7) {
3460                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3461                         correct = False;
3462                 }
3463         }
3464
3465
3466         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3467         cli_openx(cli, fname, 
3468                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3469         cli_close(cli, fnum);
3470         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3471                                 &m_time_ts, &size, NULL, NULL);
3472         if (!NT_STATUS_IS_OK(status)) {
3473                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3474                 correct = False;
3475         } else {
3476                 if (w_time_ts.tv_sec < 60*60*24*2) {
3477                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3478                         printf("This system appears to set a initial 0 write time\n");
3479                         correct = False;
3480                 }
3481         }
3482
3483         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3484
3485
3486         /* check if the server updates the directory modification time
3487            when creating a new file */
3488         status = cli_mkdir(cli, dname);
3489         if (!NT_STATUS_IS_OK(status)) {
3490                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3491                 correct = False;
3492         }
3493         sleep(3);
3494         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3495                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3496         if (!NT_STATUS_IS_OK(status)) {
3497                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3498                 correct = False;
3499         }
3500
3501         cli_openx(cli, fname2, 
3502                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3503         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3504         cli_close(cli, fnum);
3505         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3506                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3507         if (!NT_STATUS_IS_OK(status)) {
3508                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3509                 correct = False;
3510         } else {
3511                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3512                     == 0) {
3513                         printf("This system does not update directory modification times\n");
3514                         correct = False;
3515                 }
3516         }
3517         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3518         cli_rmdir(cli, dname);
3519
3520         if (!torture_close_connection(cli)) {
3521                 correct = False;
3522         }
3523
3524         printf("trans2 test finished\n");
3525
3526         return correct;
3527 }
3528
3529 /*
3530   This checks new W2K calls.
3531 */
3532
3533 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3534 {
3535         uint8_t *buf = NULL;
3536         uint32_t len;
3537         NTSTATUS status;
3538
3539         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3540                                CLI_BUFFER_SIZE, NULL, &buf, &len);
3541         if (!NT_STATUS_IS_OK(status)) {
3542                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3543                        nt_errstr(status));
3544         } else {
3545                 printf("qfileinfo: level %d, len = %u\n", level, len);
3546                 dump_data(0, (uint8_t *)buf, len);
3547                 printf("\n");
3548         }
3549         TALLOC_FREE(buf);
3550         return status;
3551 }
3552
3553 static bool run_w2ktest(int dummy)
3554 {
3555         struct cli_state *cli;
3556         uint16_t fnum;
3557         const char *fname = "\\w2ktest\\w2k.tst";
3558         int level;
3559         bool correct = True;
3560
3561         printf("starting w2k test\n");
3562
3563         if (!torture_open_connection(&cli, 0)) {
3564                 return False;
3565         }
3566
3567         cli_openx(cli, fname, 
3568                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3569
3570         for (level = 1004; level < 1040; level++) {
3571                 new_trans(cli, fnum, level);
3572         }
3573
3574         cli_close(cli, fnum);
3575
3576         if (!torture_close_connection(cli)) {
3577                 correct = False;
3578         }
3579
3580         printf("w2k test finished\n");
3581
3582         return correct;
3583 }
3584
3585
3586 /*
3587   this is a harness for some oplock tests
3588  */
3589 static bool run_oplock1(int dummy)
3590 {
3591         struct cli_state *cli1;
3592         const char *fname = "\\lockt1.lck";
3593         uint16_t fnum1;
3594         bool correct = True;
3595         NTSTATUS status;
3596
3597         printf("starting oplock test 1\n");
3598
3599         if (!torture_open_connection(&cli1, 0)) {
3600                 return False;
3601         }
3602
3603         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3604
3605         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3606
3607         cli1->use_oplocks = True;
3608
3609         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3610                           &fnum1);
3611         if (!NT_STATUS_IS_OK(status)) {
3612                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3613                 return False;
3614         }
3615
3616         cli1->use_oplocks = False;
3617
3618         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3619         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3620
3621         status = cli_close(cli1, fnum1);
3622         if (!NT_STATUS_IS_OK(status)) {
3623                 printf("close2 failed (%s)\n", nt_errstr(status));
3624                 return False;
3625         }
3626
3627         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3628         if (!NT_STATUS_IS_OK(status)) {
3629                 printf("unlink failed (%s)\n", nt_errstr(status));
3630                 return False;
3631         }
3632
3633         if (!torture_close_connection(cli1)) {
3634                 correct = False;
3635         }
3636
3637         printf("finished oplock test 1\n");
3638
3639         return correct;
3640 }
3641
3642 static bool run_oplock2(int dummy)
3643 {
3644         struct cli_state *cli1, *cli2;
3645         const char *fname = "\\lockt2.lck";
3646         uint16_t fnum1, fnum2;
3647         int saved_use_oplocks = use_oplocks;
3648         char buf[4];
3649         bool correct = True;
3650         volatile bool *shared_correct;
3651         size_t nread;
3652         NTSTATUS status;
3653
3654         shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
3655         *shared_correct = True;
3656
3657         use_level_II_oplocks = True;
3658         use_oplocks = True;
3659
3660         printf("starting oplock test 2\n");
3661
3662         if (!torture_open_connection(&cli1, 0)) {
3663                 use_level_II_oplocks = False;
3664                 use_oplocks = saved_use_oplocks;
3665                 return False;
3666         }
3667
3668         if (!torture_open_connection(&cli2, 1)) {
3669                 use_level_II_oplocks = False;
3670                 use_oplocks = saved_use_oplocks;
3671                 return False;
3672         }
3673
3674         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3675
3676         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3677         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3678
3679         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3680                           &fnum1);
3681         if (!NT_STATUS_IS_OK(status)) {
3682                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3683                 return False;
3684         }
3685
3686         /* Don't need the globals any more. */
3687         use_level_II_oplocks = False;
3688         use_oplocks = saved_use_oplocks;
3689
3690         if (fork() == 0) {
3691                 /* Child code */
3692                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3693                 if (!NT_STATUS_IS_OK(status)) {
3694                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3695                         *shared_correct = False;
3696                         exit(0);
3697                 }
3698
3699                 sleep(2);
3700
3701                 status = cli_close(cli2, fnum2);
3702                 if (!NT_STATUS_IS_OK(status)) {
3703                         printf("close2 failed (%s)\n", nt_errstr(status));
3704                         *shared_correct = False;
3705                 }
3706
3707                 exit(0);
3708         }
3709
3710         sleep(2);
3711
3712         /* Ensure cli1 processes the break. Empty file should always return 0
3713          * bytes.  */
3714         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3715         if (!NT_STATUS_IS_OK(status)) {
3716                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3717                 correct = false;
3718         } else if (nread != 0) {
3719                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3720                       (unsigned long)nread, 0);
3721                 correct = false;
3722         }
3723
3724         /* Should now be at level II. */
3725         /* Test if sending a write locks causes a break to none. */
3726         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3727         if (!NT_STATUS_IS_OK(status)) {
3728                 printf("lock failed (%s)\n", nt_errstr(status));
3729                 correct = False;
3730         }
3731
3732         cli_unlock(cli1, fnum1, 0, 4);
3733
3734         sleep(2);
3735
3736         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3737         if (!NT_STATUS_IS_OK(status)) {
3738                 printf("lock failed (%s)\n", nt_errstr(status));
3739                 correct = False;
3740         }
3741
3742         cli_unlock(cli1, fnum1, 0, 4);
3743
3744         sleep(2);
3745
3746         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3747
3748         status = cli_close(cli1, fnum1);
3749         if (!NT_STATUS_IS_OK(status)) {
3750                 printf("close1 failed (%s)\n", nt_errstr(status));
3751                 correct = False;
3752         }
3753
3754         sleep(4);
3755
3756         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3757         if (!NT_STATUS_IS_OK(status)) {
3758                 printf("unlink failed (%s)\n", nt_errstr(status));
3759                 correct = False;
3760         }
3761
3762         if (!torture_close_connection(cli1)) {
3763                 correct = False;
3764         }
3765
3766         if (!*shared_correct) {
3767                 correct = False;
3768         }
3769
3770         printf("finished oplock test 2\n");
3771
3772         return correct;
3773 }
3774
3775 struct oplock4_state {
3776         struct tevent_context *ev;
3777         struct cli_state *cli;
3778         bool *got_break;
3779         uint16_t *fnum2;
3780 };
3781
3782 static void oplock4_got_break(struct tevent_req *req);
3783 static void oplock4_got_open(struct tevent_req *req);
3784
3785 static bool run_oplock4(int dummy)
3786 {
3787         struct tevent_context *ev;
3788         struct cli_state *cli1, *cli2;
3789         struct tevent_req *oplock_req, *open_req;
3790         const char *fname = "\\lockt4.lck";
3791         const char *fname_ln = "\\lockt4_ln.lck";
3792         uint16_t fnum1, fnum2;
3793         int saved_use_oplocks = use_oplocks;
3794         NTSTATUS status;
3795         bool correct = true;
3796
3797         bool got_break;
3798
3799         struct oplock4_state *state;
3800
3801         printf("starting oplock test 4\n");
3802
3803         if (!torture_open_connection(&cli1, 0)) {
3804                 use_level_II_oplocks = false;
3805                 use_oplocks = saved_use_oplocks;
3806                 return false;
3807         }
3808
3809         if (!torture_open_connection(&cli2, 1)) {
3810                 use_level_II_oplocks = false;
3811                 use_oplocks = saved_use_oplocks;
3812                 return false;
3813         }
3814
3815         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3816         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3817
3818         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3819         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3820
3821         /* Create the file. */
3822         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3823                           &fnum1);
3824         if (!NT_STATUS_IS_OK(status)) {
3825                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3826                 return false;
3827         }
3828
3829         status = cli_close(cli1, fnum1);
3830         if (!NT_STATUS_IS_OK(status)) {
3831                 printf("close1 failed (%s)\n", nt_errstr(status));
3832                 return false;
3833         }
3834
3835         /* Now create a hardlink. */
3836         status = cli_nt_hardlink(cli1, fname, fname_ln);
3837         if (!NT_STATUS_IS_OK(status)) {
3838                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3839                 return false;
3840         }
3841
3842         /* Prove that opening hardlinks cause deny modes to conflict. */
3843         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3844         if (!NT_STATUS_IS_OK(status)) {
3845                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3846                 return false;
3847         }
3848
3849         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3850         if (NT_STATUS_IS_OK(status)) {
3851                 printf("open of %s succeeded - should fail with sharing violation.\n",
3852                         fname_ln);
3853                 return false;
3854         }
3855
3856         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3857                 printf("open of %s should fail with sharing violation. Got %s\n",
3858                         fname_ln, nt_errstr(status));
3859                 return false;
3860         }
3861
3862         status = cli_close(cli1, fnum1);
3863         if (!NT_STATUS_IS_OK(status)) {
3864                 printf("close1 failed (%s)\n", nt_errstr(status));
3865                 return false;
3866         }
3867
3868         cli1->use_oplocks = true;
3869         cli2->use_oplocks = true;
3870
3871         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3872         if (!NT_STATUS_IS_OK(status)) {
3873                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3874                 return false;
3875         }
3876
3877         ev = samba_tevent_context_init(talloc_tos());
3878         if (ev == NULL) {
3879                 printf("tevent_context_init failed\n");
3880                 return false;
3881         }
3882
3883         state = talloc(ev, struct oplock4_state);
3884         if (state == NULL) {
3885                 printf("talloc failed\n");
3886                 return false;
3887         }
3888         state->ev = ev;
3889         state->cli = cli1;
3890         state->got_break = &got_break;
3891         state->fnum2 = &fnum2;
3892
3893         oplock_req = cli_smb_oplock_break_waiter_send(
3894                 talloc_tos(), ev, cli1);
3895         if (oplock_req == NULL) {
3896                 printf("cli_smb_oplock_break_waiter_send failed\n");
3897                 return false;
3898         }
3899         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3900
3901         open_req = cli_openx_send(
3902                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3903         if (open_req == NULL) {
3904                 printf("cli_openx_send failed\n");
3905                 return false;
3906         }
3907         tevent_req_set_callback(open_req, oplock4_got_open, state);
3908
3909         got_break = false;
3910         fnum2 = 0xffff;
3911
3912         while (!got_break || fnum2 == 0xffff) {
3913                 int ret;
3914                 ret = tevent_loop_once(ev);
3915                 if (ret == -1) {
3916                         printf("tevent_loop_once failed: %s\n",
3917                                strerror(errno));
3918                         return false;
3919                 }
3920         }
3921
3922         status = cli_close(cli2, fnum2);
3923         if (!NT_STATUS_IS_OK(status)) {
3924                 printf("close2 failed (%s)\n", nt_errstr(status));
3925                 correct = false;
3926         }
3927
3928         status = cli_close(cli1, fnum1);
3929         if (!NT_STATUS_IS_OK(status)) {
3930                 printf("close1 failed (%s)\n", nt_errstr(status));
3931                 correct = false;
3932         }
3933
3934         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3935         if (!NT_STATUS_IS_OK(status)) {
3936                 printf("unlink failed (%s)\n", nt_errstr(status));
3937                 correct = false;
3938         }
3939
3940         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3941         if (!NT_STATUS_IS_OK(status)) {
3942                 printf("unlink failed (%s)\n", nt_errstr(status));
3943                 correct = false;
3944         }
3945
3946         if (!torture_close_connection(cli1)) {
3947                 correct = false;
3948         }
3949
3950         if (!got_break) {
3951                 correct = false;
3952         }
3953
3954         printf("finished oplock test 4\n");
3955
3956         return correct;
3957 }
3958
3959 static void oplock4_got_break(struct tevent_req *req)
3960 {
3961         struct oplock4_state *state = tevent_req_callback_data(
3962                 req, struct oplock4_state);
3963         uint16_t fnum;
3964         uint8_t level;
3965         NTSTATUS status;
3966
3967         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3968         TALLOC_FREE(req);
3969         if (!NT_STATUS_IS_OK(status)) {
3970                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3971                        nt_errstr(status));
3972                 return;
3973         }
3974         *state->got_break = true;
3975
3976         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3977                                   NO_OPLOCK);
3978         if (req == NULL) {
3979                 printf("cli_oplock_ack_send failed\n");
3980                 return;
3981         }
3982 }
3983
3984 static void oplock4_got_open(struct tevent_req *req)
3985 {
3986         struct oplock4_state *state = tevent_req_callback_data(
3987                 req, struct oplock4_state);
3988         NTSTATUS status;
3989
3990         status = cli_openx_recv(req, state->fnum2);
3991         if (!NT_STATUS_IS_OK(status)) {
3992                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3993                 *state->fnum2 = 0xffff;
3994         }
3995 }
3996
3997 /*
3998   Test delete on close semantics.
3999  */
4000 static bool run_deletetest(int dummy)
4001 {
4002         struct cli_state *cli1 = NULL;
4003         struct cli_state *cli2 = NULL;
4004         const char *fname = "\\delete.file";
4005         uint16_t fnum1 = (uint16_t)-1;
4006         uint16_t fnum2 = (uint16_t)-1;
4007         bool correct = false;
4008         NTSTATUS status;
4009
4010         printf("starting delete test\n");
4011
4012         if (!torture_open_connection(&cli1, 0)) {
4013                 return False;
4014         }
4015
4016         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4017
4018         /* Test 1 - this should delete the file on close. */
4019
4020         cli_setatr(cli1, fname, 0, 0);
4021         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4022
4023         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
4024                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4025                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4026         if (!NT_STATUS_IS_OK(status)) {
4027                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
4028                 goto fail;
4029         }
4030
4031         status = cli_close(cli1, fnum1);
4032         if (!NT_STATUS_IS_OK(status)) {
4033                 printf("[1] close failed (%s)\n", nt_errstr(status));
4034                 goto fail;
4035         }
4036
4037         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4038         if (NT_STATUS_IS_OK(status)) {
4039                 printf("[1] open of %s succeeded (should fail)\n", fname);
4040                 goto fail;
4041         }
4042
4043         printf("first delete on close test succeeded.\n");
4044
4045         /* Test 2 - this should delete the file on close. */
4046
4047         cli_setatr(cli1, fname, 0, 0);
4048         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4049
4050         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4051                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4052                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4053         if (!NT_STATUS_IS_OK(status)) {
4054                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
4055                 goto fail;
4056         }
4057
4058         status = cli_nt_delete_on_close(cli1, fnum1, true);
4059         if (!NT_STATUS_IS_OK(status)) {
4060                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
4061                 goto fail;
4062         }
4063
4064         status = cli_close(cli1, fnum1);
4065         if (!NT_STATUS_IS_OK(status)) {
4066                 printf("[2] close failed (%s)\n", nt_errstr(status));
4067                 goto fail;
4068         }
4069
4070         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4071         if (NT_STATUS_IS_OK(status)) {
4072                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
4073                 status = cli_close(cli1, fnum1);
4074                 if (!NT_STATUS_IS_OK(status)) {
4075                         printf("[2] close failed (%s)\n", nt_errstr(status));
4076                 }
4077                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4078                 goto fail;
4079         }
4080
4081         printf("second delete on close test succeeded.\n");
4082
4083         /* Test 3 - ... */
4084         cli_setatr(cli1, fname, 0, 0);
4085         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4086
4087         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
4088                               FILE_ATTRIBUTE_NORMAL,
4089                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4090                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4091         if (!NT_STATUS_IS_OK(status)) {
4092                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4093                 goto fail;
4094         }
4095
4096         /* This should fail with a sharing violation - open for delete is only compatible
4097            with SHARE_DELETE. */
4098
4099         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4100                               FILE_ATTRIBUTE_NORMAL,
4101                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4102                               FILE_OPEN, 0, 0, &fnum2, NULL);
4103         if (NT_STATUS_IS_OK(status)) {
4104                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
4105                 goto fail;
4106         }
4107
4108         /* This should succeed. */
4109         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4110                              FILE_ATTRIBUTE_NORMAL,
4111                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4112                              FILE_OPEN, 0, 0, &fnum2, NULL);
4113         if (!NT_STATUS_IS_OK(status)) {
4114                 printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
4115                 goto fail;
4116         }
4117
4118         status = cli_nt_delete_on_close(cli1, fnum1, true);
4119         if (!NT_STATUS_IS_OK(status)) {
4120                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4121                 goto fail;
4122         }
4123
4124         status = cli_close(cli1, fnum1);
4125         if (!NT_STATUS_IS_OK(status)) {
4126                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4127                 goto fail;
4128         }
4129
4130         status = cli_close(cli1, fnum2);
4131         if (!NT_STATUS_IS_OK(status)) {
4132                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4133                 goto fail;
4134         }
4135
4136         /* This should fail - file should no longer be there. */
4137
4138         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4139         if (NT_STATUS_IS_OK(status)) {
4140                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4141                 status = cli_close(cli1, fnum1);
4142                 if (!NT_STATUS_IS_OK(status)) {
4143                         printf("[3] close failed (%s)\n", nt_errstr(status));
4144                 }
4145                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4146                 goto fail;
4147         }
4148
4149         printf("third delete on close test succeeded.\n");
4150
4151         /* Test 4 ... */
4152         cli_setatr(cli1, fname, 0, 0);
4153         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4154
4155         status = cli_ntcreate(cli1, fname, 0,
4156                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4157                               FILE_ATTRIBUTE_NORMAL,
4158                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4159                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4160         if (!NT_STATUS_IS_OK(status)) {
4161                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4162                 goto fail;
4163         }
4164
4165         /* This should succeed. */
4166         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4167                              FILE_ATTRIBUTE_NORMAL,
4168                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4169                              FILE_OPEN, 0, 0, &fnum2, NULL);
4170         if (!NT_STATUS_IS_OK(status)) {
4171                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4172                 goto fail;
4173         }
4174
4175         status = cli_close(cli1, fnum2);
4176         if (!NT_STATUS_IS_OK(status)) {
4177                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4178                 goto fail;
4179         }
4180
4181         status = cli_nt_delete_on_close(cli1, fnum1, true);
4182         if (!NT_STATUS_IS_OK(status)) {
4183                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4184                 goto fail;
4185         }
4186
4187         /* This should fail - no more opens once delete on close set. */
4188         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4189                               FILE_ATTRIBUTE_NORMAL,
4190                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4191                               FILE_OPEN, 0, 0, &fnum2, NULL);
4192         if (NT_STATUS_IS_OK(status)) {
4193                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4194                 goto fail;
4195         }
4196
4197         status = cli_close(cli1, fnum1);
4198         if (!NT_STATUS_IS_OK(status)) {
4199                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4200                 goto fail;
4201         }
4202
4203         printf("fourth delete on close test succeeded.\n");
4204
4205         /* Test 5 ... */
4206         cli_setatr(cli1, fname, 0, 0);
4207         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4208
4209         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4210         if (!NT_STATUS_IS_OK(status)) {
4211                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4212                 goto fail;
4213         }
4214
4215         /* This should fail - only allowed on NT opens with DELETE access. */
4216
4217         status = cli_nt_delete_on_close(cli1, fnum1, true);
4218         if (NT_STATUS_IS_OK(status)) {
4219                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4220                 goto fail;
4221         }
4222
4223         status = cli_close(cli1, fnum1);
4224         if (!NT_STATUS_IS_OK(status)) {
4225                 printf("[5] close failed (%s)\n", nt_errstr(status));
4226                 goto fail;
4227         }
4228
4229         printf("fifth delete on close test succeeded.\n");
4230
4231         /* Test 6 ... */
4232         cli_setatr(cli1, fname, 0, 0);
4233         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4234
4235         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4236                              FILE_ATTRIBUTE_NORMAL,
4237                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4238                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4239         if (!NT_STATUS_IS_OK(status)) {
4240                 printf("[6] open of %s failed (%s)\n", fname,
4241                        nt_errstr(status));
4242                 goto fail;
4243         }
4244
4245         /* This should fail - only allowed on NT opens with DELETE access. */
4246
4247         status = cli_nt_delete_on_close(cli1, fnum1, true);
4248         if (NT_STATUS_IS_OK(status)) {
4249                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4250                 goto fail;
4251         }
4252
4253         status = cli_close(cli1, fnum1);
4254         if (!NT_STATUS_IS_OK(status)) {
4255                 printf("[6] close failed (%s)\n", nt_errstr(status));
4256                 goto fail;
4257         }
4258
4259         printf("sixth delete on close test succeeded.\n");
4260
4261         /* Test 7 ... */
4262         cli_setatr(cli1, fname, 0, 0);
4263         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4264
4265         status = cli_ntcreate(cli1, fname, 0,
4266                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4267                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4268                               0, 0, &fnum1, NULL);
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4271                 goto fail;
4272         }
4273
4274         status = cli_nt_delete_on_close(cli1, fnum1, true);
4275         if (!NT_STATUS_IS_OK(status)) {
4276                 printf("[7] setting delete_on_close on file failed !\n");
4277                 goto fail;
4278         }
4279
4280         status = cli_nt_delete_on_close(cli1, fnum1, false);
4281         if (!NT_STATUS_IS_OK(status)) {
4282                 printf("[7] unsetting delete_on_close on file failed !\n");
4283                 goto fail;
4284         }
4285
4286         status = cli_close(cli1, fnum1);
4287         if (!NT_STATUS_IS_OK(status)) {
4288                 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
4289                 goto fail;
4290         }
4291
4292         /* This next open should succeed - we reset the flag. */
4293         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4294         if (!NT_STATUS_IS_OK(status)) {
4295                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4296                 goto fail;
4297         }
4298
4299         status = cli_close(cli1, fnum1);
4300         if (!NT_STATUS_IS_OK(status)) {
4301                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4302                 goto fail;
4303         }
4304
4305         printf("seventh delete on close test succeeded.\n");
4306
4307         /* Test 8 ... */
4308         cli_setatr(cli1, fname, 0, 0);
4309         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4310
4311         if (!torture_open_connection(&cli2, 1)) {
4312                 printf("[8] failed to open second connection.\n");
4313                 goto fail;
4314         }
4315
4316         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4317
4318         status = cli_ntcreate(cli1, fname, 0,
4319                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4320                              FILE_ATTRIBUTE_NORMAL,
4321                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4322                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4323         if (!NT_STATUS_IS_OK(status)) {
4324                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4325                 goto fail;
4326         }
4327
4328         status = cli_ntcreate(cli2, fname, 0,
4329                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4330                              FILE_ATTRIBUTE_NORMAL,
4331                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4332                              FILE_OPEN, 0, 0, &fnum2, NULL);
4333         if (!NT_STATUS_IS_OK(status)) {
4334                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4335                 goto fail;
4336         }
4337
4338         status = cli_nt_delete_on_close(cli1, fnum1, true);
4339         if (!NT_STATUS_IS_OK(status)) {
4340                 printf("[8] setting delete_on_close on file failed !\n");
4341                 goto fail;
4342         }
4343
4344         status = cli_close(cli1, fnum1);
4345         if (!NT_STATUS_IS_OK(status)) {
4346                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4347                 goto fail;
4348         }
4349
4350         status = cli_close(cli2, fnum2);
4351         if (!NT_STATUS_IS_OK(status)) {
4352                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4353                 goto fail;
4354         }
4355
4356         /* This should fail.. */
4357         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4358         if (NT_STATUS_IS_OK(status)) {
4359                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4360                 goto fail;
4361         }
4362
4363         printf("eighth delete on close test succeeded.\n");
4364
4365         /* Test 9 ... */
4366
4367         /* This should fail - we need to set DELETE_ACCESS. */
4368         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4369                               FILE_ATTRIBUTE_NORMAL,
4370                               FILE_SHARE_NONE,
4371                               FILE_OVERWRITE_IF,
4372                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4373         if (NT_STATUS_IS_OK(status)) {
4374                 printf("[9] open of %s succeeded should have failed!\n", fname);
4375                 goto fail;
4376         }
4377
4378         printf("ninth delete on close test succeeded.\n");
4379
4380         /* Test 10 ... */
4381
4382         status = cli_ntcreate(cli1, fname, 0,
4383                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4384                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4385                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4386                              0, &fnum1, NULL);
4387         if (!NT_STATUS_IS_OK(status)) {
4388                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4389                 goto fail;
4390         }
4391
4392         /* This should delete the file. */
4393         status = cli_close(cli1, fnum1);
4394         if (!NT_STATUS_IS_OK(status)) {
4395                 printf("[10] close failed (%s)\n", nt_errstr(status));
4396                 goto fail;
4397         }
4398
4399         /* This should fail.. */
4400         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4401         if (NT_STATUS_IS_OK(status)) {
4402                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4403                 goto fail;
4404         }
4405
4406         printf("tenth delete on close test succeeded.\n");
4407
4408         /* Test 11 ... */
4409
4410         cli_setatr(cli1, fname, 0, 0);
4411         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4412
4413         /* Can we open a read-only file with delete access? */
4414
4415         /* Create a readonly file. */
4416         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4417                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4418                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4419         if (!NT_STATUS_IS_OK(status)) {
4420                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4421                 goto fail;
4422         }
4423
4424         status = cli_close(cli1, fnum1);
4425         if (!NT_STATUS_IS_OK(status)) {
4426                 printf("[11] close failed (%s)\n", nt_errstr(status));
4427                 goto fail;
4428         }
4429
4430         /* Now try open for delete access. */
4431         status = cli_ntcreate(cli1, fname, 0,
4432                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4433                              0,
4434                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4435                              FILE_OPEN, 0, 0, &fnum1, NULL);
4436         if (!NT_STATUS_IS_OK(status)) {
4437                 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
4438                 goto fail;
4439         }
4440
4441         cli_close(cli1, fnum1);
4442
4443         printf("eleventh delete on close test succeeded.\n");
4444
4445         /*
4446          * Test 12
4447          * like test 4 but with initial delete on close
4448          */
4449
4450         cli_setatr(cli1, fname, 0, 0);
4451         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4452
4453         status = cli_ntcreate(cli1, fname, 0,
4454                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4455                               FILE_ATTRIBUTE_NORMAL,
4456                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4457                               FILE_OVERWRITE_IF,
4458                               FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
4459         if (!NT_STATUS_IS_OK(status)) {
4460                 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4461                 goto fail;
4462         }
4463
4464         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4465                               FILE_ATTRIBUTE_NORMAL,
4466                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4467                               FILE_OPEN, 0, 0, &fnum2, NULL);
4468         if (!NT_STATUS_IS_OK(status)) {
4469                 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
4470                 goto fail;
4471         }
4472
4473         status = cli_close(cli1, fnum2);
4474         if (!NT_STATUS_IS_OK(status)) {
4475                 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
4476                 goto fail;
4477         }
4478
4479         status = cli_nt_delete_on_close(cli1, fnum1, true);
4480         if (!NT_STATUS_IS_OK(status)) {
4481                 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
4482                 goto fail;
4483         }
4484
4485         /* This should fail - no more opens once delete on close set. */
4486         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4487                               FILE_ATTRIBUTE_NORMAL,
4488                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4489                               FILE_OPEN, 0, 0, &fnum2, NULL);
4490         if (NT_STATUS_IS_OK(status)) {
4491                 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
4492                 goto fail;
4493         }
4494
4495         status = cli_nt_delete_on_close(cli1, fnum1, false);
4496         if (!NT_STATUS_IS_OK(status)) {
4497                 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
4498                 goto fail;
4499         }
4500
4501         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4502                               FILE_ATTRIBUTE_NORMAL,
4503                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4504                               FILE_OPEN, 0, 0, &fnum2, NULL);
4505         if (!NT_STATUS_IS_OK(status)) {
4506                 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
4507                 goto fail;
4508         }
4509
4510         status = cli_close(cli1, fnum2);
4511         if (!NT_STATUS_IS_OK(status)) {
4512                 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
4513                 goto fail;
4514         }
4515
4516         status = cli_close(cli1, fnum1);
4517         if (!NT_STATUS_IS_OK(status)) {
4518                 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
4519                 goto fail;
4520         }
4521
4522         /*
4523          * setting delete on close on the handle does
4524          * not unset the initial delete on close...
4525          */
4526         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4527                               FILE_ATTRIBUTE_NORMAL,
4528                               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4529                               FILE_OPEN, 0, 0, &fnum2, NULL);
4530         if (NT_STATUS_IS_OK(status)) {
4531                 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
4532                 goto fail;
4533         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4534                 printf("ntcreate returned %s, expected "
4535                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
4536                        nt_errstr(status));
4537                 goto fail;
4538         }
4539
4540         printf("twelfth delete on close test succeeded.\n");
4541
4542
4543         printf("finished delete test\n");
4544
4545         correct = true;
4546
4547   fail:
4548         /* FIXME: This will crash if we aborted before cli2 got
4549          * intialized, because these functions don't handle
4550          * uninitialized connections. */
4551
4552         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4553         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4554         cli_setatr(cli1, fname, 0, 0);
4555         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4556
4557         if (cli1 && !torture_close_connection(cli1)) {
4558                 correct = False;
4559         }
4560         if (cli2 && !torture_close_connection(cli2)) {
4561                 correct = False;
4562         }
4563         return correct;
4564 }
4565
4566 /*
4567   Exercise delete on close semantics - use on the PRINT1 share in torture
4568   testing.
4569  */
4570 static bool run_delete_print_test(int dummy)
4571 {
4572         struct cli_state *cli1 = NULL;
4573         const char *fname = "print_delete.file";
4574         uint16_t fnum1 = (uint16_t)-1;
4575         bool correct = false;
4576         const char *buf = "print file data\n";
4577         NTSTATUS status;
4578
4579         printf("starting print delete test\n");
4580
4581         if (!torture_open_connection(&cli1, 0)) {
4582                 return false;
4583         }
4584
4585         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4586
4587         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
4588                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4589                               0, 0, &fnum1, NULL);
4590         if (!NT_STATUS_IS_OK(status)) {
4591                 printf("open of %s failed (%s)\n",
4592                         fname,
4593                         nt_errstr(status));
4594                 goto fail;
4595         }
4596
4597         status = cli_writeall(cli1,
4598                         fnum1,
4599                         0,
4600                         (const uint8_t *)buf,
4601                         0, /* offset */
4602                         strlen(buf), /* size */
4603                         NULL);
4604         if (!NT_STATUS_IS_OK(status)) {
4605                 printf("writing print file data failed (%s)\n",
4606                         nt_errstr(status));
4607                 goto fail;
4608         }
4609
4610         status = cli_nt_delete_on_close(cli1, fnum1, true);
4611         if (!NT_STATUS_IS_OK(status)) {
4612                 printf("setting delete_on_close failed (%s)\n",
4613                         nt_errstr(status));
4614                 goto fail;
4615         }
4616
4617         status = cli_close(cli1, fnum1);
4618         if (!NT_STATUS_IS_OK(status)) {
4619                 printf("close failed (%s)\n", nt_errstr(status));
4620                 goto fail;
4621         }
4622
4623         printf("finished print delete test\n");
4624
4625         correct = true;
4626
4627   fail:
4628
4629         if (fnum1 != (uint16_t)-1) {
4630                 cli_close(cli1, fnum1);
4631         }
4632
4633         if (cli1 && !torture_close_connection(cli1)) {
4634                 correct = false;
4635         }
4636         return correct;
4637 }
4638
4639 /*
4640   Test wildcard delete.
4641  */
4642 static bool run_wild_deletetest(int dummy)
4643 {
4644         struct cli_state *cli = NULL;
4645         const char *dname = "\\WTEST";
4646         const char *fname = "\\WTEST\\A";
4647         const char *wunlink_name = "\\WTEST\\*";
4648         uint16_t fnum1 = (uint16_t)-1;
4649         bool correct = false;
4650         NTSTATUS status;
4651
4652         printf("starting wildcard delete test\n");
4653
4654         if (!torture_open_connection(&cli, 0)) {
4655                 return false;
4656         }
4657
4658         smbXcli_conn_set_sockopt(cli->conn, sockops);
4659
4660         cli_unlink(cli, fname, 0);
4661         cli_rmdir(cli, dname);
4662         status = cli_mkdir(cli, dname);
4663         if (!NT_STATUS_IS_OK(status)) {
4664                 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
4665                 goto fail;
4666         }
4667         status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
4668         if (!NT_STATUS_IS_OK(status)) {
4669                 printf("open of %s failed %s!\n", fname, nt_errstr(status));
4670                 goto fail;
4671         }
4672         status = cli_close(cli, fnum1);
4673         fnum1 = -1;
4674
4675         /*
4676          * Note the unlink attribute-type of zero. This should
4677          * map into FILE_ATTRIBUTE_NORMAL at the server even
4678          * on a wildcard delete.
4679          */
4680
4681         status = cli_unlink(cli, wunlink_name, 0);
4682         if (!NT_STATUS_IS_OK(status)) {
4683                 printf("unlink of %s failed %s!\n",
4684                         wunlink_name, nt_errstr(status));
4685                 goto fail;
4686         }
4687
4688         printf("finished wildcard delete test\n");
4689
4690         correct = true;
4691
4692   fail:
4693
4694         if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
4695         cli_unlink(cli, fname, 0);
4696         cli_rmdir(cli, dname);
4697
4698         if (cli && !torture_close_connection(cli)) {
4699                 correct = false;
4700         }
4701         return correct;
4702 }
4703
4704 static bool run_deletetest_ln(int dummy)
4705 {
4706         struct cli_state *cli;
4707         const char *fname = "\\delete1";
4708         const char *fname_ln = "\\delete1_ln";
4709         uint16_t fnum;
4710         uint16_t fnum1;
4711         NTSTATUS status;
4712         bool correct = true;
4713         time_t t;
4714
4715         printf("starting deletetest-ln\n");
4716
4717         if (!torture_open_connection(&cli, 0)) {
4718                 return false;
4719         }
4720
4721         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4722         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4723
4724         smbXcli_conn_set_sockopt(cli->conn, sockops);
4725
4726         /* Create the file. */
4727         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4728         if (!NT_STATUS_IS_OK(status)) {
4729                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4730                 return false;
4731         }
4732
4733         status = cli_close(cli, fnum);
4734         if (!NT_STATUS_IS_OK(status)) {
4735                 printf("close1 failed (%s)\n", nt_errstr(status));
4736                 return false;
4737         }
4738
4739         /* Now create a hardlink. */
4740         status = cli_nt_hardlink(cli, fname, fname_ln);
4741         if (!NT_STATUS_IS_OK(status)) {
4742                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4743                 return false;
4744         }
4745
4746         /* Open the original file. */
4747         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4748                         FILE_ATTRIBUTE_NORMAL,
4749                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4750                         FILE_OPEN_IF, 0, 0, &fnum, NULL);
4751         if (!NT_STATUS_IS_OK(status)) {
4752                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4753                 return false;
4754         }
4755
4756         /* Unlink the hard link path. */
4757         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4758                         FILE_ATTRIBUTE_NORMAL,
4759                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4760                         FILE_OPEN_IF, 0, 0, &fnum1, NULL);
4761         if (!NT_STATUS_IS_OK(status)) {
4762                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4763                 return false;
4764         }
4765         status = cli_nt_delete_on_close(cli, fnum1, true);
4766         if (!NT_STATUS_IS_OK(status)) {
4767                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4768                         __location__, fname_ln, nt_errstr(status));
4769                 return false;
4770         }
4771
4772         status = cli_close(cli, fnum1);
4773         if (!NT_STATUS_IS_OK(status)) {
4774                 printf("close %s failed (%s)\n",
4775                         fname_ln, nt_errstr(status));
4776                 return false;
4777         }
4778
4779         status = cli_close(cli, fnum);
4780         if (!NT_STATUS_IS_OK(status)) {
4781                 printf("close %s failed (%s)\n",
4782                         fname, nt_errstr(status));
4783                 return false;
4784         }
4785
4786         /* Ensure the original file is still there. */
4787         status = cli_getatr(cli, fname, NULL, NULL, &t);
4788         if (!NT_STATUS_IS_OK(status)) {
4789                 printf("%s getatr on file %s failed (%s)\n",
4790                         __location__,
4791                         fname,
4792                         nt_errstr(status));
4793                 correct = False;
4794         }
4795
4796         /* Ensure the link path is gone. */
4797         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4798         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4799                 printf("%s, getatr for file %s returned wrong error code %s "
4800                         "- should have been deleted\n",
4801                         __location__,
4802                         fname_ln, nt_errstr(status));
4803                 correct = False;
4804         }
4805
4806         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4807         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4808
4809         if (!torture_close_connection(cli)) {
4810                 correct = false;
4811         }
4812
4813         printf("finished deletetest-ln\n");
4814
4815         return correct;
4816 }
4817
4818 /*
4819   print out server properties
4820  */
4821 static bool run_properties(int dummy)
4822 {
4823         struct cli_state *cli;
4824         bool correct = True;
4825
4826         printf("starting properties test\n");
4827
4828         ZERO_STRUCT(cli);
4829
4830         if (!torture_open_connection(&cli, 0)) {
4831                 return False;
4832         }
4833
4834         smbXcli_conn_set_sockopt(cli->conn, sockops);
4835
4836         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4837
4838         if (!torture_close_connection(cli)) {
4839                 correct = False;
4840         }
4841
4842         return correct;
4843 }
4844
4845
4846
4847 /* FIRST_DESIRED_ACCESS   0xf019f */
4848 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4849                                FILE_READ_EA|                           /* 0xf */ \
4850                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4851                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4852                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4853                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4854 /* SECOND_DESIRED_ACCESS  0xe0080 */
4855 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4856                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4857                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4858
4859 #if 0
4860 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4861                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4862                                FILE_READ_DATA|\
4863                                WRITE_OWNER_ACCESS                      /* */
4864 #endif
4865
4866 /*
4867   Test ntcreate calls made by xcopy
4868  */
4869 static bool run_xcopy(int dummy)
4870 {
4871         static struct cli_state *cli1;
4872         const char *fname = "\\test.txt";
4873         bool correct = True;
4874         uint16_t fnum1, fnum2;
4875         NTSTATUS status;
4876
4877         printf("starting xcopy test\n");
4878
4879         if (!torture_open_connection(&cli1, 0)) {
4880                 return False;
4881         }
4882
4883         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4884                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4885                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
4886         if (!NT_STATUS_IS_OK(status)) {
4887                 printf("First open failed - %s\n", nt_errstr(status));
4888                 return False;
4889         }
4890
4891         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4892                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4893                              FILE_OPEN, 0x200000, 0, &fnum2, NULL);
4894         if (!NT_STATUS_IS_OK(status)) {
4895                 printf("second open failed - %s\n", nt_errstr(status));
4896                 return False;
4897         }
4898
4899         if (!torture_close_connection(cli1)) {
4900                 correct = False;
4901         }
4902
4903         return correct;
4904 }
4905
4906 /*
4907   Test rename on files open with share delete and no share delete.
4908  */
4909 static bool run_rename(int dummy)
4910 {
4911         static struct cli_state *cli1;
4912         const char *fname = "\\test.txt";
4913         const char *fname1 = "\\test1.txt";
4914         bool correct = True;
4915         uint16_t fnum1;
4916         uint16_t attr;
4917         NTSTATUS status;
4918
4919         printf("starting rename test\n");
4920
4921         if (!torture_open_connection(&cli1, 0)) {
4922                 return False;
4923         }
4924
4925         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4926         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4927
4928         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4929                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4930                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4931         if (!NT_STATUS_IS_OK(status)) {
4932                 printf("First open failed - %s\n", nt_errstr(status));
4933                 return False;
4934         }
4935
4936         status = cli_rename(cli1, fname, fname1, false);
4937         if (!NT_STATUS_IS_OK(status)) {
4938                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4939         } else {
4940                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4941                 correct = False;
4942         }
4943
4944         status = cli_close(cli1, fnum1);
4945         if (!NT_STATUS_IS_OK(status)) {
4946                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4947                 return False;
4948         }
4949
4950         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4951         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4952         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4953 #if 0
4954                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4955 #else
4956                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4957 #endif
4958                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4959         if (!NT_STATUS_IS_OK(status)) {
4960                 printf("Second open failed - %s\n", nt_errstr(status));
4961                 return False;
4962         }
4963
4964         status = cli_rename(cli1, fname, fname1, false);
4965         if (!NT_STATUS_IS_OK(status)) {
4966                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4967                 correct = False;
4968         } else {
4969                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4970         }
4971
4972         status = cli_close(cli1, fnum1);
4973         if (!NT_STATUS_IS_OK(status)) {
4974                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4975                 return False;
4976         }
4977
4978         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4979         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4980
4981         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4982                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4983                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
4984         if (!NT_STATUS_IS_OK(status)) {
4985                 printf("Third open failed - %s\n", nt_errstr(status));
4986                 return False;
4987         }
4988
4989
4990 #if 0
4991   {
4992         uint16_t fnum2;
4993
4994         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4995                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
4996                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4997                 return False;
4998         }
4999         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
5000                 printf("[8] setting delete_on_close on file failed !\n");
5001                 return False;
5002         }
5003
5004         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
5005                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
5006                 return False;
5007         }
5008   }
5009 #endif
5010
5011         status = cli_rename(cli1, fname, fname1, false);
5012         if (!NT_STATUS_IS_OK(status)) {
5013                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
5014                 correct = False;
5015         } else {
5016                 printf("Third rename succeeded (SHARE_NONE)\n");
5017         }
5018
5019         status = cli_close(cli1, fnum1);
5020         if (!NT_STATUS_IS_OK(status)) {
5021                 printf("close - 3 failed (%s)\n", nt_errstr(status));
5022                 return False;
5023         }
5024
5025         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5026         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5027
5028         /*----*/
5029
5030         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5031                               FILE_ATTRIBUTE_NORMAL,
5032                               FILE_SHARE_READ | FILE_SHARE_WRITE,
5033                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5034         if (!NT_STATUS_IS_OK(status)) {
5035                 printf("Fourth open failed - %s\n", nt_errstr(status));
5036                 return False;
5037         }
5038
5039         status = cli_rename(cli1, fname, fname1, false);
5040         if (!NT_STATUS_IS_OK(status)) {
5041                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
5042         } else {
5043                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
5044                 correct = False;
5045         }
5046
5047         status = cli_close(cli1, fnum1);
5048         if (!NT_STATUS_IS_OK(status)) {
5049                 printf("close - 4 failed (%s)\n", nt_errstr(status));
5050                 return False;
5051         }
5052
5053         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5054         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5055
5056         /*--*/
5057
5058         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5059                          FILE_ATTRIBUTE_NORMAL,
5060                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5061                          FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5062         if (!NT_STATUS_IS_OK(status)) {
5063                 printf("Fifth open failed - %s\n", nt_errstr(status));
5064                 return False;
5065         }
5066
5067         status = cli_rename(cli1, fname, fname1, false);
5068         if (!NT_STATUS_IS_OK(status)) {
5069                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
5070                 correct = False;
5071         } else {
5072                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
5073         }
5074
5075         /*
5076          * Now check if the first name still exists ...
5077          */
5078
5079         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
5080                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5081                                    FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
5082           printf("Opening original file after rename of open file fails: %s\n",
5083               cli_errstr(cli1));
5084         }
5085         else {
5086           printf("Opening original file after rename of open file works ...\n");
5087           (void)cli_close(cli1, fnum2);
5088           } */
5089
5090         /*--*/
5091         status = cli_close(cli1, fnum1);
5092         if (!NT_STATUS_IS_OK(status)) {
5093                 printf("close - 5 failed (%s)\n", nt_errstr(status));
5094                 return False;
5095         }
5096
5097         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
5098         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
5099         if (!NT_STATUS_IS_OK(status)) {
5100                 printf("getatr on file %s failed - %s ! \n",
5101                         fname1, nt_errstr(status));
5102                 correct = False;
5103         } else {
5104                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
5105                         printf("Renamed file %s has wrong attr 0x%x "
5106                                 "(should be 0x%x)\n",
5107                                 fname1,
5108                                 attr,
5109                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
5110                         correct = False;
5111                 } else {
5112                         printf("Renamed file %s has archive bit set\n", fname1);
5113                 }
5114         }
5115
5116         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5117         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5118
5119         if (!torture_close_connection(cli1)) {
5120                 correct = False;
5121         }
5122
5123         return correct;
5124 }
5125
5126 /*
5127   Test rename into a directory with an ACL denying it.
5128  */
5129 static bool run_rename_access(int dummy)
5130 {
5131         static struct cli_state *cli = NULL;
5132         static struct cli_state *posix_cli = NULL;
5133         const char *src = "test.txt";
5134         const char *dname = "dir";
5135         const char *dst = "dir\\test.txt";
5136         const char *dsrc = "test.dir";
5137         const char *ddst = "dir\\test.dir";
5138         uint16_t fnum = (uint16_t)-1;
5139         struct security_descriptor *sd = NULL;
5140         struct security_descriptor *newsd = NULL;
5141         NTSTATUS status;
5142         TALLOC_CTX *frame = NULL;
5143
5144         frame = talloc_stackframe();
5145         printf("starting rename access test\n");
5146
5147         /* Windows connection. */
5148         if (!torture_open_connection(&cli, 0)) {
5149                 goto fail;
5150         }
5151
5152         smbXcli_conn_set_sockopt(cli->conn, sockops);
5153
5154         /* Posix connection. */
5155         if (!torture_open_connection(&posix_cli, 0)) {
5156                 goto fail;
5157         }
5158
5159         smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
5160
5161         status = torture_setup_unix_extensions(posix_cli);
5162         if (!NT_STATUS_IS_OK(status)) {
5163                 goto fail;
5164         }
5165
5166         /* Start with a clean slate. */
5167         cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5168         cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5169         cli_rmdir(cli, dsrc);
5170         cli_rmdir(cli, ddst);
5171         cli_rmdir(cli, dname);
5172
5173         /*
5174          * Setup the destination directory with a DENY ACE to
5175          * prevent new files within it.
5176          */
5177         status = cli_ntcreate(cli,
5178                                 dname,
5179                                 0,
5180                                 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
5181                                         WRITE_DAC_ACCESS|FILE_READ_DATA|
5182                                         WRITE_OWNER_ACCESS,
5183                                 FILE_ATTRIBUTE_DIRECTORY,
5184                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
5185                                 FILE_CREATE,
5186                                 FILE_DIRECTORY_FILE,
5187                                 0,
5188                                 &fnum,
5189                                 NULL);
5190         if (!NT_STATUS_IS_OK(status)) {
5191                 printf("Create of %s - %s\n", dname, nt_errstr(status));
5192                 goto fail;
5193         }
5194
5195         status = cli_query_secdesc(cli,
5196                                 fnum,
5197                                 frame,
5198                                 &sd);
5199         if (!NT_STATUS_IS_OK(status)) {
5200                 printf("cli_query_secdesc failed for %s (%s)\n",
5201                         dname, nt_errstr(status));
5202                 goto fail;
5203         }
5204
5205         newsd = security_descriptor_dacl_create(frame,
5206                                         0,
5207                                         NULL,
5208                                         NULL,
5209                                         SID_WORLD,
5210                                         SEC_ACE_TYPE_ACCESS_DENIED,
5211                                         SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
5212                                         0,
5213                                         NULL);
5214         if (newsd == NULL) {
5215                 goto fail;
5216         }
5217         sd->dacl = security_acl_concatenate(frame,
5218                                         newsd->dacl,
5219                                         sd->dacl);
5220         if (sd->dacl == NULL) {
5221                 goto fail;
5222         }
5223         status = cli_set_secdesc(cli, fnum, sd);
5224         if (!NT_STATUS_IS_OK(status)) {
5225                 printf("cli_set_secdesc failed for %s (%s)\n",
5226                         dname, nt_errstr(status));
5227                 goto fail;
5228         }
5229         status = cli_close(cli, fnum);
5230         if (!NT_STATUS_IS_OK(status)) {
5231                 printf("close failed for %s (%s)\n",
5232                         dname, nt_errstr(status));
5233                 goto fail;
5234         }
5235         /* Now go around the back and chmod to 777 via POSIX. */
5236         status = cli_posix_chmod(posix_cli, dname, 0777);
5237         if (!NT_STATUS_IS_OK(status)) {
5238                 printf("cli_posix_chmod failed for %s (%s)\n",
5239                         dname, nt_errstr(status));
5240                 goto fail;
5241         }
5242
5243         /* Check we can't create a file within dname via Windows. */
5244         status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5245         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5246                 cli_close(posix_cli, fnum);
5247                 printf("Create of %s should be ACCESS denied, was %s\n",
5248                         dst, nt_errstr(status));
5249                 goto fail;
5250         }
5251
5252         /* Make the sample file/directory. */
5253         status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5254         if (!NT_STATUS_IS_OK(status)) {
5255                 printf("open of %s failed (%s)\n", src, nt_errstr(status));
5256                 goto fail;
5257         }
5258         status = cli_close(cli, fnum);
5259         if (!NT_STATUS_IS_OK(status)) {
5260                 printf("cli_close failed (%s)\n", nt_errstr(status));
5261                 goto fail;
5262         }
5263
5264         status = cli_mkdir(cli, dsrc);
5265         if (!NT_STATUS_IS_OK(status)) {
5266                 printf("cli_mkdir of %s failed (%s)\n",
5267                         dsrc, nt_errstr(status));
5268                 goto fail;
5269         }
5270
5271         /*
5272          * OK - renames of the new file and directory into the
5273          * dst directory should fail.
5274          */
5275
5276         status = cli_rename(cli, src, dst, false);
5277         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5278                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5279                         src, dst, nt_errstr(status));
5280                 goto fail;
5281         }
5282         status = cli_rename(cli, dsrc, ddst, false);
5283         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5284                 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
5285                         src, dst, nt_errstr(status));
5286                 goto fail;
5287         }
5288
5289         TALLOC_FREE(frame);
5290         return true;
5291
5292   fail:
5293
5294         if (posix_cli) {
5295                 torture_close_connection(posix_cli);
5296         }
5297
5298         if (cli) {
5299                 if (fnum != (uint16_t)-1) {
5300                         cli_close(cli, fnum);
5301                 }
5302                 cli_unlink(cli, src,
5303                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5304                 cli_unlink(cli, dst,
5305                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5306                 cli_rmdir(cli, dsrc);
5307                 cli_rmdir(cli, ddst);
5308                 cli_rmdir(cli, dname);
5309
5310                 torture_close_connection(cli);
5311         }
5312
5313         TALLOC_FREE(frame);
5314         return false;
5315 }
5316
5317 /*
5318   Test owner rights ACE.
5319  */
5320 static bool run_owner_rights(int dummy)
5321 {
5322         static struct cli_state *cli = NULL;
5323         const char *fname = "owner_rights.txt";
5324         uint16_t fnum = (uint16_t)-1;
5325         struct security_descriptor *sd = NULL;
5326         struct security_descriptor *newsd = NULL;
5327         NTSTATUS status;
5328         TALLOC_CTX *frame = NULL;
5329
5330         frame = talloc_stackframe();
5331         printf("starting owner rights test\n");
5332
5333         /* Windows connection. */
5334         if (!torture_open_connection(&cli, 0)) {
5335                 goto fail;
5336         }
5337
5338         smbXcli_conn_set_sockopt(cli->conn, sockops);
5339
5340         /* Start with a clean slate. */
5341         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5342
5343         /* Create the test file. */
5344         /* Now try and open for read and write-dac. */
5345         status = cli_ntcreate(cli,
5346                                 fname,
5347                                 0,
5348                                 GENERIC_ALL_ACCESS,
5349                                 FILE_ATTRIBUTE_NORMAL,
5350                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5351                                         FILE_SHARE_DELETE,
5352                                 FILE_CREATE,
5353                                 0,
5354                                 0,
5355                                 &fnum,
5356                                 NULL);
5357         if (!NT_STATUS_IS_OK(status)) {
5358                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5359                 goto fail;
5360         }
5361
5362         /* Get the original SD. */
5363         status = cli_query_secdesc(cli,
5364                                 fnum,
5365                                 frame,
5366                                 &sd);
5367         if (!NT_STATUS_IS_OK(status)) {
5368                 printf("cli_query_secdesc failed for %s (%s)\n",
5369                         fname, nt_errstr(status));
5370                 goto fail;
5371         }
5372
5373         /*
5374          * Add an "owner-rights" ACE denying WRITE_DATA,
5375          * and an "owner-rights" ACE allowing READ_DATA.
5376          */
5377
5378         newsd = security_descriptor_dacl_create(frame,
5379                                         0,
5380                                         NULL,
5381                                         NULL,
5382                                         SID_OWNER_RIGHTS,
5383                                         SEC_ACE_TYPE_ACCESS_DENIED,
5384                                         FILE_WRITE_DATA,
5385                                         0,
5386                                         SID_OWNER_RIGHTS,
5387                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5388                                         FILE_READ_DATA,
5389                                         0,
5390                                         NULL);
5391         if (newsd == NULL) {
5392                 goto fail;
5393         }
5394         sd->dacl = security_acl_concatenate(frame,
5395                                         newsd->dacl,
5396                                         sd->dacl);
5397         if (sd->dacl == NULL) {
5398                 goto fail;
5399         }
5400         status = cli_set_secdesc(cli, fnum, sd);
5401         if (!NT_STATUS_IS_OK(status)) {
5402                 printf("cli_set_secdesc failed for %s (%s)\n",
5403                         fname, nt_errstr(status));
5404                 goto fail;
5405         }
5406         status = cli_close(cli, fnum);
5407         if (!NT_STATUS_IS_OK(status)) {
5408                 printf("close failed for %s (%s)\n",
5409                         fname, nt_errstr(status));
5410                 goto fail;
5411         }
5412         fnum = (uint16_t)-1;
5413
5414         /* Try and open for FILE_WRITE_DATA */
5415         status = cli_ntcreate(cli,
5416                                 fname,
5417                                 0,
5418                                 FILE_WRITE_DATA,
5419                                 FILE_ATTRIBUTE_NORMAL,
5420                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5421                                         FILE_SHARE_DELETE,
5422                                 FILE_OPEN,
5423                                 0,
5424                                 0,
5425                                 &fnum,
5426                                 NULL);
5427         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5428                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5429                 goto fail;
5430         }
5431
5432         /* Now try and open for FILE_READ_DATA */
5433         status = cli_ntcreate(cli,
5434                                 fname,
5435                                 0,
5436                                 FILE_READ_DATA,
5437                                 FILE_ATTRIBUTE_NORMAL,
5438                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5439                                         FILE_SHARE_DELETE,
5440                                 FILE_OPEN,
5441                                 0,
5442                                 0,
5443                                 &fnum,
5444                                 NULL);
5445         if (!NT_STATUS_IS_OK(status)) {
5446                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5447                 goto fail;
5448         }
5449
5450         status = cli_close(cli, fnum);
5451         if (!NT_STATUS_IS_OK(status)) {
5452                 printf("close failed for %s (%s)\n",
5453                         fname, nt_errstr(status));
5454                 goto fail;
5455         }
5456
5457         /* Restore clean slate. */
5458         TALLOC_FREE(sd);
5459         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5460
5461         /* Create the test file. */
5462         status = cli_ntcreate(cli,
5463                                 fname,
5464                                 0,
5465                                 GENERIC_ALL_ACCESS,
5466                                 FILE_ATTRIBUTE_NORMAL,
5467                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5468                                         FILE_SHARE_DELETE,
5469                                 FILE_CREATE,
5470                                 0,
5471                                 0,
5472                                 &fnum,
5473                                 NULL);
5474         if (!NT_STATUS_IS_OK(status)) {
5475                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5476                 goto fail;
5477         }
5478
5479         /* Get the original SD. */
5480         status = cli_query_secdesc(cli,
5481                                 fnum,
5482                                 frame,
5483                                 &sd);
5484         if (!NT_STATUS_IS_OK(status)) {
5485                 printf("cli_query_secdesc failed for %s (%s)\n",
5486                         fname, nt_errstr(status));
5487                 goto fail;
5488         }
5489
5490         /*
5491          * Add an "owner-rights ACE denying WRITE_DATA,
5492          * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
5493          */
5494
5495         newsd = security_descriptor_dacl_create(frame,
5496                                         0,
5497                                         NULL,
5498                                         NULL,
5499                                         SID_OWNER_RIGHTS,
5500                                         SEC_ACE_TYPE_ACCESS_DENIED,
5501                                         FILE_WRITE_DATA,
5502                                         0,
5503                                         SID_OWNER_RIGHTS,
5504                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5505                                         FILE_READ_DATA|FILE_WRITE_DATA,
5506                                         0,
5507                                         NULL);
5508         if (newsd == NULL) {
5509                 goto fail;
5510         }
5511         sd->dacl = security_acl_concatenate(frame,
5512                                         newsd->dacl,
5513                                         sd->dacl);
5514         if (sd->dacl == NULL) {
5515                 goto fail;
5516         }
5517         status = cli_set_secdesc(cli, fnum, sd);
5518         if (!NT_STATUS_IS_OK(status)) {
5519                 printf("cli_set_secdesc failed for %s (%s)\n",
5520                         fname, nt_errstr(status));
5521                 goto fail;
5522         }
5523         status = cli_close(cli, fnum);
5524         if (!NT_STATUS_IS_OK(status)) {
5525                 printf("close failed for %s (%s)\n",
5526                         fname, nt_errstr(status));
5527                 goto fail;
5528         }
5529         fnum = (uint16_t)-1;
5530
5531         /* Try and open for FILE_WRITE_DATA */
5532         status = cli_ntcreate(cli,
5533                                 fname,
5534                                 0,
5535                                 FILE_WRITE_DATA,
5536                                 FILE_ATTRIBUTE_NORMAL,
5537                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5538                                         FILE_SHARE_DELETE,
5539                                 FILE_OPEN,
5540                                 0,
5541                                 0,
5542                                 &fnum,
5543                                 NULL);
5544         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5545                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5546                 goto fail;
5547         }
5548
5549         /* Now try and open for FILE_READ_DATA */
5550         status = cli_ntcreate(cli,
5551                                 fname,
5552                                 0,
5553                                 FILE_READ_DATA,
5554                                 FILE_ATTRIBUTE_NORMAL,
5555                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5556                                         FILE_SHARE_DELETE,
5557                                 FILE_OPEN,
5558                                 0,
5559                                 0,
5560                                 &fnum,
5561                                 NULL);
5562         if (!NT_STATUS_IS_OK(status)) {
5563                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5564                 goto fail;
5565         }
5566
5567         status = cli_close(cli, fnum);
5568         if (!NT_STATUS_IS_OK(status)) {
5569                 printf("close failed for %s (%s)\n",
5570                         fname, nt_errstr(status));
5571                 goto fail;
5572         }
5573
5574         /* Restore clean slate. */
5575         TALLOC_FREE(sd);
5576         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5577
5578
5579         /* Create the test file. */
5580         status = cli_ntcreate(cli,
5581                                 fname,
5582                                 0,
5583                                 GENERIC_ALL_ACCESS,
5584                                 FILE_ATTRIBUTE_NORMAL,
5585                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5586                                         FILE_SHARE_DELETE,
5587                                 FILE_CREATE,
5588                                 0,
5589                                 0,
5590                                 &fnum,
5591                                 NULL);
5592         if (!NT_STATUS_IS_OK(status)) {
5593                 printf("Create of %s - %s\n", fname, nt_errstr(status));
5594                 goto fail;
5595         }
5596
5597         /* Get the original SD. */
5598         status = cli_query_secdesc(cli,
5599                                 fnum,
5600                                 frame,
5601                                 &sd);
5602         if (!NT_STATUS_IS_OK(status)) {
5603                 printf("cli_query_secdesc failed for %s (%s)\n",
5604                         fname, nt_errstr(status));
5605                 goto fail;
5606         }
5607
5608         /*
5609          * Add an "authenticated users" ACE allowing READ_DATA,
5610          * add an "owner-rights" denying READ_DATA,
5611          * and an "authenticated users" ACE allowing WRITE_DATA.
5612          */
5613
5614         newsd = security_descriptor_dacl_create(frame,
5615                                         0,
5616                                         NULL,
5617                                         NULL,
5618                                         SID_NT_AUTHENTICATED_USERS,
5619                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5620                                         FILE_READ_DATA,
5621                                         0,
5622                                         SID_OWNER_RIGHTS,
5623                                         SEC_ACE_TYPE_ACCESS_DENIED,
5624                                         FILE_READ_DATA,
5625                                         0,
5626                                         SID_NT_AUTHENTICATED_USERS,
5627                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
5628                                         FILE_WRITE_DATA,
5629                                         0,
5630                                         NULL);
5631         if (newsd == NULL) {
5632                 printf("newsd == NULL\n");
5633                 goto fail;
5634         }
5635         sd->dacl = security_acl_concatenate(frame,
5636                                         newsd->dacl,
5637                                         sd->dacl);
5638         if (sd->dacl == NULL) {
5639                 printf("sd->dacl == NULL\n");
5640                 goto fail;
5641         }
5642         status = cli_set_secdesc(cli, fnum, sd);
5643         if (!NT_STATUS_IS_OK(status)) {
5644                 printf("cli_set_secdesc failed for %s (%s)\n",
5645                         fname, nt_errstr(status));
5646                 goto fail;
5647         }
5648         status = cli_close(cli, fnum);
5649         if (!NT_STATUS_IS_OK(status)) {
5650                 printf("close failed for %s (%s)\n",
5651                         fname, nt_errstr(status));
5652                 goto fail;
5653         }
5654         fnum = (uint16_t)-1;
5655
5656         /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
5657         status = cli_ntcreate(cli,
5658                                 fname,
5659                                 0,
5660                                 FILE_READ_DATA|FILE_WRITE_DATA,
5661                                 FILE_ATTRIBUTE_NORMAL,
5662                                 FILE_SHARE_READ|FILE_SHARE_WRITE|
5663                                         FILE_SHARE_DELETE,
5664                                 FILE_OPEN,
5665                                 0,
5666                                 0,
5667                                 &fnum,
5668                                 NULL);
5669         if (!NT_STATUS_IS_OK(status)) {
5670                 printf("Open of %s - %s\n", fname, nt_errstr(status));
5671                 goto fail;
5672         }
5673
5674         status = cli_close(cli, fnum);
5675         if (!NT_STATUS_IS_OK(status)) {
5676                 printf("close failed for %s (%s)\n",
5677                         fname, nt_errstr(status));
5678                 goto fail;
5679         }
5680
5681         cli_unlink(cli, fname,
5682                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5683
5684         TALLOC_FREE(frame);
5685         return true;
5686
5687   fail:
5688
5689         if (cli) {
5690                 if (fnum != (uint16_t)-1) {
5691                         cli_close(cli, fnum);
5692                 }
5693                 cli_unlink(cli, fname,
5694                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5695                 torture_close_connection(cli);
5696         }
5697
5698         TALLOC_FREE(frame);
5699         return false;
5700 }
5701
5702 static bool run_pipe_number(int dummy)
5703 {
5704         struct cli_state *cli1;
5705         const char *pipe_name = "\\SPOOLSS";
5706         uint16_t fnum;
5707         int num_pipes = 0;
5708         NTSTATUS status;
5709
5710         printf("starting pipenumber test\n");
5711         if (!torture_open_connection(&cli1, 0)) {
5712                 return False;
5713         }
5714
5715         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5716         while(1) {
5717                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
5718                                       FILE_ATTRIBUTE_NORMAL,
5719                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
5720                                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
5721                 if (!NT_STATUS_IS_OK(status)) {
5722                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
5723                         break;
5724                 }
5725                 num_pipes++;
5726                 printf("\r%6d", num_pipes);
5727         }
5728
5729         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
5730         torture_close_connection(cli1);
5731         return True;
5732 }
5733
5734 /*
5735   Test open mode returns on read-only files.
5736  */
5737 static bool run_opentest(int dummy)
5738 {
5739         static struct cli_state *cli1;
5740         static struct cli_state *cli2;
5741         const char *fname = "\\readonly.file";
5742         uint16_t fnum1, fnum2;
5743         char buf[20];
5744         off_t fsize;
5745         bool correct = True;
5746         char *tmp_path;
5747         NTSTATUS status;
5748
5749         printf("starting open test\n");
5750
5751         if (!torture_open_connection(&cli1, 0)) {
5752                 return False;
5753         }
5754
5755         cli_setatr(cli1, fname, 0, 0);
5756         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5757
5758         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5759
5760         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5761         if (!NT_STATUS_IS_OK(status)) {
5762                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5763                 return False;
5764         }
5765
5766         status = cli_close(cli1, fnum1);
5767         if (!NT_STATUS_IS_OK(status)) {
5768                 printf("close2 failed (%s)\n", nt_errstr(status));
5769                 return False;
5770         }
5771
5772         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
5773         if (!NT_STATUS_IS_OK(status)) {
5774                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
5775                 return False;
5776         }
5777
5778         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5779         if (!NT_STATUS_IS_OK(status)) {
5780                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5781                 return False;
5782         }
5783
5784         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
5785         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5786
5787         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
5788                         NT_STATUS_ACCESS_DENIED)) {
5789                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
5790         }
5791
5792         printf("finished open test 1\n");
5793
5794         cli_close(cli1, fnum1);
5795
5796         /* Now try not readonly and ensure ERRbadshare is returned. */
5797
5798         cli_setatr(cli1, fname, 0, 0);
5799
5800         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
5801         if (!NT_STATUS_IS_OK(status)) {
5802                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5803                 return False;
5804         }
5805
5806         /* This will fail - but the error should be ERRshare. */
5807         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
5808
5809         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
5810                         NT_STATUS_SHARING_VIOLATION)) {
5811                 printf("correct error code ERRDOS/ERRbadshare returned\n");
5812         }
5813
5814         status = cli_close(cli1, fnum1);
5815         if (!NT_STATUS_IS_OK(status)) {
5816                 printf("close2 failed (%s)\n", nt_errstr(status));
5817                 return False;
5818         }
5819
5820         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5821
5822         printf("finished open test 2\n");
5823
5824         /* Test truncate open disposition on file opened for read. */
5825         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
5826         if (!NT_STATUS_IS_OK(status)) {
5827                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
5828                 return False;
5829         }
5830
5831         /* write 20 bytes. */
5832
5833         memset(buf, '\0', 20);
5834
5835         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
5836         if (!NT_STATUS_IS_OK(status)) {
5837                 printf("write failed (%s)\n", nt_errstr(status));
5838                 correct = False;
5839         }
5840
5841         status = cli_close(cli1, fnum1);
5842         if (!NT_STATUS_IS_OK(status)) {
5843                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
5844                 return False;
5845         }
5846
5847         /* Ensure size == 20. */
5848         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5849         if (!NT_STATUS_IS_OK(status)) {
5850                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5851                 return False;
5852         }
5853
5854         if (fsize != 20) {
5855                 printf("(3) file size != 20\n");
5856                 return False;
5857         }
5858
5859         /* Now test if we can truncate a file opened for readonly. */
5860         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
5861         if (!NT_STATUS_IS_OK(status)) {
5862                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
5863                 return False;
5864         }
5865
5866         status = cli_close(cli1, fnum1);
5867         if (!NT_STATUS_IS_OK(status)) {
5868                 printf("close2 failed (%s)\n", nt_errstr(status));
5869                 return False;
5870         }
5871
5872         /* Ensure size == 0. */
5873         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
5874         if (!NT_STATUS_IS_OK(status)) {
5875                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
5876                 return False;
5877         }
5878
5879         if (fsize != 0) {
5880                 printf("(3) file size != 0\n");
5881                 return False;
5882         }
5883         printf("finished open test 3\n");
5884
5885         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5886
5887         printf("Do ctemp tests\n");
5888         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5889         if (!NT_STATUS_IS_OK(status)) {
5890                 printf("ctemp failed (%s)\n", nt_errstr(status));
5891                 return False;
5892         }
5893
5894         printf("ctemp gave path %s\n", tmp_path);
5895         status = cli_close(cli1, fnum1);
5896         if (!NT_STATUS_IS_OK(status)) {
5897                 printf("close of temp failed (%s)\n", nt_errstr(status));
5898         }
5899
5900         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5901         if (!NT_STATUS_IS_OK(status)) {
5902                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5903         }
5904
5905         /* Test the non-io opens... */
5906
5907         if (!torture_open_connection(&cli2, 1)) {
5908                 return False;
5909         }
5910
5911         cli_setatr(cli2, fname, 0, 0);
5912         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5913
5914         smbXcli_conn_set_sockopt(cli2->conn, sockops);
5915
5916         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5917         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5918                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5919                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5920         if (!NT_STATUS_IS_OK(status)) {
5921                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5922                 return False;
5923         }
5924
5925         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5926                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5927                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5928         if (!NT_STATUS_IS_OK(status)) {
5929                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5930                 return False;
5931         }
5932
5933         status = cli_close(cli1, fnum1);
5934         if (!NT_STATUS_IS_OK(status)) {
5935                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5936                 return False;
5937         }
5938
5939         status = cli_close(cli2, fnum2);
5940         if (!NT_STATUS_IS_OK(status)) {
5941                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5942                 return False;
5943         }
5944
5945         printf("non-io open test #1 passed.\n");
5946
5947         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5948
5949         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5950
5951         status = cli_ntcreate(cli1, fname, 0,
5952                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5953                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5954                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5955         if (!NT_STATUS_IS_OK(status)) {
5956                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5957                 return False;
5958         }
5959
5960         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5961                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5962                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5963         if (!NT_STATUS_IS_OK(status)) {
5964                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5965                 return False;
5966         }
5967
5968         status = cli_close(cli1, fnum1);
5969         if (!NT_STATUS_IS_OK(status)) {
5970                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5971                 return False;
5972         }
5973
5974         status = cli_close(cli2, fnum2);
5975         if (!NT_STATUS_IS_OK(status)) {
5976                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5977                 return False;
5978         }
5979
5980         printf("non-io open test #2 passed.\n");
5981
5982         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5983
5984         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5985
5986         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5987                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5988                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5989         if (!NT_STATUS_IS_OK(status)) {
5990                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5991                 return False;
5992         }
5993
5994         status = cli_ntcreate(cli2, fname, 0,
5995                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5996                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5997                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
5998         if (!NT_STATUS_IS_OK(status)) {
5999                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6000                 return False;
6001         }
6002
6003         status = cli_close(cli1, fnum1);
6004         if (!NT_STATUS_IS_OK(status)) {
6005                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6006                 return False;
6007         }
6008
6009         status = cli_close(cli2, fnum2);
6010         if (!NT_STATUS_IS_OK(status)) {
6011                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6012                 return False;
6013         }
6014
6015         printf("non-io open test #3 passed.\n");
6016
6017         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6018
6019         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
6020
6021         status = cli_ntcreate(cli1, fname, 0,
6022                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6023                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6024                                FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6025         if (!NT_STATUS_IS_OK(status)) {
6026                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6027                 return False;
6028         }
6029
6030         status = cli_ntcreate(cli2, fname, 0,
6031                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6032                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6033                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6034         if (NT_STATUS_IS_OK(status)) {
6035                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
6036                 return False;
6037         }
6038
6039         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
6040
6041         status = cli_close(cli1, fnum1);
6042         if (!NT_STATUS_IS_OK(status)) {
6043                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6044                 return False;
6045         }
6046
6047         printf("non-io open test #4 passed.\n");
6048
6049         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6050
6051         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
6052
6053         status = cli_ntcreate(cli1, fname, 0,
6054                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6055                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
6056                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6057         if (!NT_STATUS_IS_OK(status)) {
6058                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6059                 return False;
6060         }
6061
6062         status = cli_ntcreate(cli2, fname, 0,
6063                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6064                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
6065                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6066         if (!NT_STATUS_IS_OK(status)) {
6067                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6068                 return False;
6069         }
6070
6071         status = cli_close(cli1, fnum1);
6072         if (!NT_STATUS_IS_OK(status)) {
6073                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6074                 return False;
6075         }
6076
6077         status = cli_close(cli2, fnum2);
6078         if (!NT_STATUS_IS_OK(status)) {
6079                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6080                 return False;
6081         }
6082
6083         printf("non-io open test #5 passed.\n");
6084
6085         printf("TEST #6 testing 1 non-io open, one io open\n");
6086
6087         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6088
6089         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6090                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6091                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6092         if (!NT_STATUS_IS_OK(status)) {
6093                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6094                 return False;
6095         }
6096
6097         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
6098                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6099                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6100         if (!NT_STATUS_IS_OK(status)) {
6101                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
6102                 return False;
6103         }
6104
6105         status = cli_close(cli1, fnum1);
6106         if (!NT_STATUS_IS_OK(status)) {
6107                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6108                 return False;
6109         }
6110
6111         status = cli_close(cli2, fnum2);
6112         if (!NT_STATUS_IS_OK(status)) {
6113                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
6114                 return False;
6115         }
6116
6117         printf("non-io open test #6 passed.\n");
6118
6119         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
6120
6121         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6122
6123         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
6124                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6125                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6126         if (!NT_STATUS_IS_OK(status)) {
6127                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
6128                 return False;
6129         }
6130
6131         status = cli_ntcreate(cli2, fname, 0,
6132                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
6133                               FILE_ATTRIBUTE_NORMAL,
6134                               FILE_SHARE_READ|FILE_SHARE_DELETE,
6135                               FILE_OPEN_IF, 0, 0, &fnum2, NULL);
6136         if (NT_STATUS_IS_OK(status)) {
6137                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
6138                 return False;
6139         }
6140
6141         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
6142
6143         status = cli_close(cli1, fnum1);
6144         if (!NT_STATUS_IS_OK(status)) {
6145                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
6146                 return False;
6147         }
6148
6149         printf("non-io open test #7 passed.\n");
6150
6151         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6152
6153         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
6154         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
6155                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6156                                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6157         if (!NT_STATUS_IS_OK(status)) {
6158                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
6159                 correct = false;
6160                 goto out;
6161         }
6162
6163         /* Write to ensure we have to update the file time. */
6164         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6165                               NULL);
6166         if (!NT_STATUS_IS_OK(status)) {
6167                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
6168                 correct = false;
6169                 goto out;
6170         }
6171
6172         status = cli_close(cli1, fnum1);
6173         if (!NT_STATUS_IS_OK(status)) {
6174                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
6175                 correct = false;
6176         }
6177
6178   out:
6179
6180         if (!torture_close_connection(cli1)) {
6181                 correct = False;
6182         }
6183         if (!torture_close_connection(cli2)) {
6184                 correct = False;
6185         }
6186
6187         return correct;
6188 }
6189
6190 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
6191 {
6192         uint16_t major, minor;
6193         uint32_t caplow, caphigh;
6194         NTSTATUS status;
6195
6196         if (!SERVER_HAS_UNIX_CIFS(cli)) {
6197                 printf("Server doesn't support UNIX CIFS extensions.\n");
6198                 return NT_STATUS_NOT_SUPPORTED;
6199         }
6200
6201         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
6202                                              &caphigh);
6203         if (!NT_STATUS_IS_OK(status)) {
6204                 printf("Server didn't return UNIX CIFS extensions: %s\n",
6205                        nt_errstr(status));
6206                 return status;
6207         }
6208
6209         status = cli_set_unix_extensions_capabilities(cli, major, minor,
6210                                                       caplow, caphigh);
6211         if (!NT_STATUS_IS_OK(status)) {
6212                 printf("Server doesn't support setting UNIX CIFS extensions: "
6213                        "%s.\n", nt_errstr(status));
6214                 return status;
6215         }
6216
6217         return NT_STATUS_OK;
6218 }
6219
6220 /*
6221   Test POSIX open /mkdir calls.
6222  */
6223 static bool run_simple_posix_open_test(int dummy)
6224 {
6225         static struct cli_state *cli1;
6226         const char *fname = "posix:file";
6227         const char *hname = "posix:hlink";
6228         const char *sname = "posix:symlink";
6229         const char *dname = "posix:dir";
6230         char buf[10];
6231         char namebuf[11];
6232         uint16_t fnum1 = (uint16_t)-1;
6233         SMB_STRUCT_STAT sbuf;
6234         bool correct = false;
6235         NTSTATUS status;
6236         size_t nread;
6237         const char *fname_windows = "windows_file";
6238         uint16_t fnum2 = (uint16_t)-1;
6239
6240         printf("Starting simple POSIX open test\n");
6241
6242         if (!torture_open_connection(&cli1, 0)) {
6243                 return false;
6244         }
6245
6246         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6247
6248         status = torture_setup_unix_extensions(cli1);
6249         if (!NT_STATUS_IS_OK(status)) {
6250                 return false;
6251         }
6252
6253         cli_setatr(cli1, fname, 0, 0);
6254         cli_posix_unlink(cli1, fname);
6255         cli_setatr(cli1, dname, 0, 0);
6256         cli_posix_rmdir(cli1, dname);
6257         cli_setatr(cli1, hname, 0, 0);
6258         cli_posix_unlink(cli1, hname);
6259         cli_setatr(cli1, sname, 0, 0);
6260         cli_posix_unlink(cli1, sname);
6261         cli_setatr(cli1, fname_windows, 0, 0);
6262         cli_posix_unlink(cli1, fname_windows);
6263
6264         /* Create a directory. */
6265         status = cli_posix_mkdir(cli1, dname, 0777);
6266         if (!NT_STATUS_IS_OK(status)) {
6267                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6268                 goto out;
6269         }
6270
6271         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6272                                 0600, &fnum1);
6273         if (!NT_STATUS_IS_OK(status)) {
6274                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6275                 goto out;
6276         }
6277
6278         /* Test ftruncate - set file size. */
6279         status = cli_ftruncate(cli1, fnum1, 1000);
6280         if (!NT_STATUS_IS_OK(status)) {
6281                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6282                 goto out;
6283         }
6284
6285         /* Ensure st_size == 1000 */
6286         status = cli_posix_stat(cli1, fname, &sbuf);
6287         if (!NT_STATUS_IS_OK(status)) {
6288                 printf("stat failed (%s)\n", nt_errstr(status));
6289                 goto out;
6290         }
6291
6292         if (sbuf.st_ex_size != 1000) {
6293                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6294                 goto out;
6295         }
6296
6297         /* Ensure st_mode == 0600 */
6298         if ((sbuf.st_ex_mode & 07777) != 0600) {
6299                 printf("posix_open - bad permissions 0%o != 0600\n",
6300                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6301                 goto out;
6302         }
6303
6304         /* Test ftruncate - set file size back to zero. */
6305         status = cli_ftruncate(cli1, fnum1, 0);
6306         if (!NT_STATUS_IS_OK(status)) {
6307                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6308                 goto out;
6309         }
6310
6311         status = cli_close(cli1, fnum1);
6312         if (!NT_STATUS_IS_OK(status)) {
6313                 printf("close failed (%s)\n", nt_errstr(status));
6314                 goto out;
6315         }
6316
6317         /* Now open the file again for read only. */
6318         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6319         if (!NT_STATUS_IS_OK(status)) {
6320                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
6321                 goto out;
6322         }
6323
6324         /* Now unlink while open. */
6325         status = cli_posix_unlink(cli1, fname);
6326         if (!NT_STATUS_IS_OK(status)) {
6327                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6328                 goto out;
6329         }
6330
6331         status = cli_close(cli1, fnum1);
6332         if (!NT_STATUS_IS_OK(status)) {
6333                 printf("close(2) failed (%s)\n", nt_errstr(status));
6334                 goto out;
6335         }
6336
6337         /* Ensure the file has gone. */
6338         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
6339         if (NT_STATUS_IS_OK(status)) {
6340                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
6341                 goto out;
6342         }
6343
6344         /* Create again to test open with O_TRUNC. */
6345         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
6346         if (!NT_STATUS_IS_OK(status)) {
6347                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6348                 goto out;
6349         }
6350
6351         /* Test ftruncate - set file size. */
6352         status = cli_ftruncate(cli1, fnum1, 1000);
6353         if (!NT_STATUS_IS_OK(status)) {
6354                 printf("ftruncate failed (%s)\n", nt_errstr(status));
6355                 goto out;
6356         }
6357
6358         /* Ensure st_size == 1000 */
6359         status = cli_posix_stat(cli1, fname, &sbuf);
6360         if (!NT_STATUS_IS_OK(status)) {
6361                 printf("stat failed (%s)\n", nt_errstr(status));
6362                 goto out;
6363         }
6364
6365         if (sbuf.st_ex_size != 1000) {
6366                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
6367                 goto out;
6368         }
6369
6370         status = cli_close(cli1, fnum1);
6371         if (!NT_STATUS_IS_OK(status)) {
6372                 printf("close(2) failed (%s)\n", nt_errstr(status));
6373                 goto out;
6374         }
6375
6376         /* Re-open with O_TRUNC. */
6377         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
6378         if (!NT_STATUS_IS_OK(status)) {
6379                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6380                 goto out;
6381         }
6382
6383         /* Ensure st_size == 0 */
6384         status = cli_posix_stat(cli1, fname, &sbuf);
6385         if (!NT_STATUS_IS_OK(status)) {
6386                 printf("stat failed (%s)\n", nt_errstr(status));
6387                 goto out;
6388         }
6389
6390         if (sbuf.st_ex_size != 0) {
6391                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
6392                 goto out;
6393         }
6394
6395         status = cli_close(cli1, fnum1);
6396         if (!NT_STATUS_IS_OK(status)) {
6397                 printf("close failed (%s)\n", nt_errstr(status));
6398                 goto out;
6399         }
6400
6401         status = cli_posix_unlink(cli1, fname);
6402         if (!NT_STATUS_IS_OK(status)) {
6403                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
6404                 goto out;
6405         }
6406
6407         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
6408         if (!NT_STATUS_IS_OK(status)) {
6409                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
6410                         dname, nt_errstr(status));
6411                 goto out;
6412         }
6413
6414         cli_close(cli1, fnum1);
6415
6416         /* What happens when we try and POSIX open a directory for write ? */
6417         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
6418         if (NT_STATUS_IS_OK(status)) {
6419                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
6420                 goto out;
6421         } else {
6422                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6423                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6424                         goto out;
6425                 }
6426         }
6427
6428         /* Create the file. */
6429         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6430                                 0600, &fnum1);
6431         if (!NT_STATUS_IS_OK(status)) {
6432                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6433                 goto out;
6434         }
6435
6436         /* Write some data into it. */
6437         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6438                               NULL);
6439         if (!NT_STATUS_IS_OK(status)) {
6440                 printf("cli_write failed: %s\n", nt_errstr(status));
6441                 goto out;
6442         }
6443
6444         cli_close(cli1, fnum1);
6445
6446         /* Now create a hardlink. */
6447         status = cli_posix_hardlink(cli1, fname, hname);
6448         if (!NT_STATUS_IS_OK(status)) {
6449                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6450                 goto out;
6451         }
6452
6453         /* Now create a symlink. */
6454         status = cli_posix_symlink(cli1, fname, sname);
6455         if (!NT_STATUS_IS_OK(status)) {
6456                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6457                 goto out;
6458         }
6459
6460         /* Open the hardlink for read. */
6461         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6462         if (!NT_STATUS_IS_OK(status)) {
6463                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6464                 goto out;
6465         }
6466
6467         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6468         if (!NT_STATUS_IS_OK(status)) {
6469                 printf("POSIX read of %s failed (%s)\n", hname,
6470                        nt_errstr(status));
6471                 goto out;
6472         } else if (nread != 10) {
6473                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6474                        hname, (unsigned long)nread, 10);
6475                 goto out;
6476         }
6477
6478         if (memcmp(buf, "TEST DATA\n", 10)) {
6479                 printf("invalid data read from hardlink\n");
6480                 goto out;
6481         }
6482
6483         /* Do a POSIX lock/unlock. */
6484         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6485         if (!NT_STATUS_IS_OK(status)) {
6486                 printf("POSIX lock failed %s\n", nt_errstr(status));
6487                 goto out;
6488         }
6489
6490         /* Punch a hole in the locked area. */
6491         status = cli_posix_unlock(cli1, fnum1, 10, 80);
6492         if (!NT_STATUS_IS_OK(status)) {
6493                 printf("POSIX unlock failed %s\n", nt_errstr(status));
6494                 goto out;
6495         }
6496
6497         cli_close(cli1, fnum1);
6498
6499         /* Open the symlink for read - this should fail. A POSIX
6500            client should not be doing opens on a symlink. */
6501         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6502         if (NT_STATUS_IS_OK(status)) {
6503                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6504                 goto out;
6505         } else {
6506                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6507                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6508                         printf("POSIX open of %s should have failed "
6509                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6510                                 "failed with %s instead.\n",
6511                                 sname, nt_errstr(status));
6512                         goto out;
6513                 }
6514         }
6515
6516         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6517         if (!NT_STATUS_IS_OK(status)) {
6518                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6519                 goto out;
6520         }
6521
6522         if (strcmp(namebuf, fname) != 0) {
6523                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6524                         sname, fname, namebuf);
6525                 goto out;
6526         }
6527
6528         status = cli_posix_rmdir(cli1, dname);
6529         if (!NT_STATUS_IS_OK(status)) {
6530                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6531                 goto out;
6532         }
6533
6534         /* Check directory opens with a specific permission. */
6535         status = cli_posix_mkdir(cli1, dname, 0700);
6536         if (!NT_STATUS_IS_OK(status)) {
6537                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6538                 goto out;
6539         }
6540
6541         /* Ensure st_mode == 0700 */
6542         status = cli_posix_stat(cli1, dname, &sbuf);
6543         if (!NT_STATUS_IS_OK(status)) {
6544                 printf("stat failed (%s)\n", nt_errstr(status));
6545                 goto out;
6546         }
6547
6548         if ((sbuf.st_ex_mode & 07777) != 0700) {
6549                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6550                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6551                 goto out;
6552         }
6553
6554         /*
6555          * Now create a Windows file, and attempt a POSIX unlink.
6556          * This should fail with a sharing violation but due to:
6557          *
6558          * [Bug 9571] Unlink after open causes smbd to panic
6559          *
6560          * ensure we've fixed the lock ordering violation.
6561          */
6562
6563         status = cli_ntcreate(cli1, fname_windows, 0,
6564                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
6565                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6566                         FILE_CREATE,
6567                         0x0, 0x0, &fnum2, NULL);
6568         if (!NT_STATUS_IS_OK(status)) {
6569                 printf("Windows create of %s failed (%s)\n", fname_windows,
6570                         nt_errstr(status));
6571                 goto out;
6572         }
6573
6574         /* Now try posix_unlink. */
6575         status = cli_posix_unlink(cli1, fname_windows);
6576         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6577                 printf("POSIX unlink of %s should fail "
6578                         "with NT_STATUS_SHARING_VIOLATION "
6579                         "got %s instead !\n",
6580                         fname_windows,
6581                         nt_errstr(status));
6582                 goto out;
6583         }
6584
6585         cli_close(cli1, fnum2);
6586
6587         printf("Simple POSIX open test passed\n");
6588         correct = true;
6589
6590   out:
6591
6592         if (fnum1 != (uint16_t)-1) {
6593                 cli_close(cli1, fnum1);
6594                 fnum1 = (uint16_t)-1;
6595         }
6596
6597         if (fnum2 != (uint16_t)-1) {
6598                 cli_close(cli1, fnum2);
6599                 fnum2 = (uint16_t)-1;
6600         }
6601
6602         cli_setatr(cli1, sname, 0, 0);
6603         cli_posix_unlink(cli1, sname);
6604         cli_setatr(cli1, hname, 0, 0);
6605         cli_posix_unlink(cli1, hname);
6606         cli_setatr(cli1, fname, 0, 0);
6607         cli_posix_unlink(cli1, fname);
6608         cli_setatr(cli1, dname, 0, 0);
6609         cli_posix_rmdir(cli1, dname);
6610         cli_setatr(cli1, fname_windows, 0, 0);
6611         cli_posix_unlink(cli1, fname_windows);
6612
6613         if (!torture_close_connection(cli1)) {
6614                 correct = false;
6615         }
6616
6617         return correct;
6618 }
6619
6620 /*
6621   Test POSIX and Windows ACLs are rejected on symlinks.
6622  */
6623 static bool run_acl_symlink_test(int dummy)
6624 {
6625         static struct cli_state *cli;
6626         const char *fname = "posix_file";
6627         const char *sname = "posix_symlink";
6628         uint16_t fnum = (uint16_t)-1;
6629         bool correct = false;
6630         NTSTATUS status;
6631         char *posix_acl = NULL;
6632         size_t posix_acl_len = 0;
6633         char *posix_acl_sym = NULL;
6634         size_t posix_acl_len_sym = 0;
6635         struct security_descriptor *sd = NULL;
6636         struct security_descriptor *sd_sym = NULL;
6637         TALLOC_CTX *frame = NULL;
6638
6639         frame = talloc_stackframe();
6640
6641         printf("Starting acl symlink test\n");
6642
6643         if (!torture_open_connection(&cli, 0)) {
6644                 TALLOC_FREE(frame);
6645                 return false;
6646         }
6647
6648         smbXcli_conn_set_sockopt(cli->conn, sockops);
6649
6650         status = torture_setup_unix_extensions(cli);
6651         if (!NT_STATUS_IS_OK(status)) {
6652                 TALLOC_FREE(frame);
6653                 return false;
6654         }
6655
6656         cli_setatr(cli, fname, 0, 0);
6657         cli_posix_unlink(cli, fname);
6658         cli_setatr(cli, sname, 0, 0);
6659         cli_posix_unlink(cli, sname);
6660
6661         status = cli_ntcreate(cli,
6662                         fname,
6663                         0,
6664                         READ_CONTROL_ACCESS,
6665                         0,
6666                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6667                         FILE_CREATE,
6668                         0x0,
6669                         0x0,
6670                         &fnum,
6671                         NULL);
6672
6673         if (!NT_STATUS_IS_OK(status)) {
6674                 printf("cli_ntcreate of %s failed (%s)\n",
6675                         fname,
6676                         nt_errstr(status));
6677                 goto out;
6678         }
6679
6680         /* Get the Windows ACL on the file. */
6681         status = cli_query_secdesc(cli,
6682                                 fnum,
6683                                 frame,
6684                                 &sd);
6685         if (!NT_STATUS_IS_OK(status)) {
6686                 printf("cli_query_secdesc failed (%s)\n",
6687                         nt_errstr(status));
6688                 goto out;
6689         }
6690
6691         /* Get the POSIX ACL on the file. */
6692         status = cli_posix_getacl(cli,
6693                                 fname,
6694                                 frame,
6695                                 &posix_acl_len,
6696                                 &posix_acl);
6697
6698         if (!NT_STATUS_IS_OK(status)) {
6699                 printf("cli_posix_getacl failed (%s)\n",
6700                         nt_errstr(status));
6701                 goto out;
6702         }
6703
6704         status = cli_close(cli, fnum);
6705         if (!NT_STATUS_IS_OK(status)) {
6706                 printf("close failed (%s)\n", nt_errstr(status));
6707                 goto out;
6708         }
6709         fnum = (uint16_t)-1;
6710
6711         /* Now create a symlink. */
6712         status = cli_posix_symlink(cli, fname, sname);
6713         if (!NT_STATUS_IS_OK(status)) {
6714                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6715                         sname,
6716                         fname,
6717                         nt_errstr(status));
6718                 goto out;
6719         }
6720
6721         /* Open a handle on the symlink. */
6722         status = cli_ntcreate(cli,
6723                         sname,
6724                         0,
6725                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6726                         0,
6727                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6728                         FILE_OPEN,
6729                         0x0,
6730                         0x0,
6731                         &fnum,
6732                         NULL);
6733
6734         if (!NT_STATUS_IS_OK(status)) {
6735                 printf("cli_posix_open of %s failed (%s)\n",
6736                         sname,
6737                         nt_errstr(status));
6738                 goto out;
6739         }
6740
6741         /* Get the Windows ACL on the symlink handle. Should fail */
6742         status = cli_query_secdesc(cli,
6743                                 fnum,
6744                                 frame,
6745                                 &sd_sym);
6746
6747         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6748                 printf("cli_query_secdesc on a symlink gave %s. "
6749                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6750                         nt_errstr(status));
6751                 goto out;
6752         }
6753
6754         /* Get the POSIX ACL on the symlink pathname. Should fail. */
6755         status = cli_posix_getacl(cli,
6756                                 sname,
6757                                 frame,
6758                                 &posix_acl_len_sym,
6759                                 &posix_acl_sym);
6760
6761         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6762                 printf("cli_posix_getacl on a symlink gave %s. "
6763                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6764                         nt_errstr(status));
6765                 goto out;
6766         }
6767
6768         /* Set the Windows ACL on the symlink handle. Should fail */
6769         status = cli_set_security_descriptor(cli,
6770                                 fnum,
6771                                 SECINFO_DACL,
6772                                 sd);
6773
6774         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6775                 printf("cli_query_secdesc on a symlink gave %s. "
6776                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6777                         nt_errstr(status));
6778                 goto out;
6779         }
6780
6781         /* Set the POSIX ACL on the symlink pathname. Should fail. */
6782         status = cli_posix_setacl(cli,
6783                                 sname,
6784                                 posix_acl,
6785                                 posix_acl_len);
6786
6787         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6788                 printf("cli_posix_getacl on a symlink gave %s. "
6789                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6790                         nt_errstr(status));
6791                 goto out;
6792         }
6793
6794         printf("ACL symlink test passed\n");
6795         correct = true;
6796
6797   out:
6798
6799         if (fnum != (uint16_t)-1) {
6800                 cli_close(cli, fnum);
6801                 fnum = (uint16_t)-1;
6802         }
6803
6804         cli_setatr(cli, sname, 0, 0);
6805         cli_posix_unlink(cli, sname);
6806         cli_setatr(cli, fname, 0, 0);
6807         cli_posix_unlink(cli, fname);
6808
6809         if (!torture_close_connection(cli)) {
6810                 correct = false;
6811         }
6812
6813         TALLOC_FREE(frame);
6814         return correct;
6815 }
6816
6817 /*
6818   Test POSIX can delete a file containing streams.
6819  */
6820 static bool run_posix_stream_delete(int dummy)
6821 {
6822         struct cli_state *cli1 = NULL;
6823         struct cli_state *cli2 = NULL;
6824         const char *fname = "streamfile";
6825         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6826         uint16_t fnum1 = (uint16_t)-1;
6827         bool correct = false;
6828         NTSTATUS status;
6829         TALLOC_CTX *frame = NULL;
6830
6831         frame = talloc_stackframe();
6832
6833         printf("Starting POSIX stream delete test\n");
6834
6835         if (!torture_open_connection(&cli1, 0) ||
6836                         !torture_open_connection(&cli2, 1)) {
6837                 TALLOC_FREE(frame);
6838                 return false;
6839         }
6840
6841         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6842         smbXcli_conn_set_sockopt(cli2->conn, sockops);
6843
6844         status = torture_setup_unix_extensions(cli2);
6845         if (!NT_STATUS_IS_OK(status)) {
6846                 goto out;
6847         }
6848
6849         cli_setatr(cli1, fname, 0, 0);
6850         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6851
6852         /* Create the file. */
6853         status = cli_ntcreate(cli1,
6854                         fname,
6855                         0,
6856                         READ_CONTROL_ACCESS,
6857                         0,
6858                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6859                         FILE_CREATE,
6860                         0x0,
6861                         0x0,
6862                         &fnum1,
6863                         NULL);
6864
6865         if (!NT_STATUS_IS_OK(status)) {
6866                 printf("cli_ntcreate of %s failed (%s)\n",
6867                         fname,
6868                         nt_errstr(status));
6869                 goto out;
6870         }
6871
6872         status = cli_close(cli1, fnum1);
6873         if (!NT_STATUS_IS_OK(status)) {
6874                 printf("cli_close of %s failed (%s)\n",
6875                         fname,
6876                         nt_errstr(status));
6877                 goto out;
6878         }
6879         fnum1 = (uint16_t)-1;
6880
6881         /* Now create the stream. */
6882         status = cli_ntcreate(cli1,
6883                         stream_fname,
6884                         0,
6885                         FILE_WRITE_DATA,
6886                         0,
6887                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6888                         FILE_CREATE,
6889                         0x0,
6890                         0x0,
6891                         &fnum1,
6892                         NULL);
6893
6894         if (!NT_STATUS_IS_OK(status)) {
6895                 printf("cli_ntcreate of %s failed (%s)\n",
6896                         stream_fname,
6897                         nt_errstr(status));
6898                 goto out;
6899         }
6900
6901         /* Leave the stream handle open... */
6902
6903         /* POSIX unlink should fail. */
6904         status = cli_posix_unlink(cli2, fname);
6905         if (NT_STATUS_IS_OK(status)) {
6906                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6907                         fname);
6908                 goto out;
6909         }
6910
6911         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6912                 printf("cli_posix_unlink of %s failed with (%s) "
6913                         "should have been NT_STATUS_SHARING_VIOLATION\n",
6914                         fname,
6915                         nt_errstr(status));
6916                 goto out;
6917         }
6918
6919         /* Close the stream handle. */
6920         status = cli_close(cli1, fnum1);
6921         if (!NT_STATUS_IS_OK(status)) {
6922                 printf("cli_close of %s failed (%s)\n",
6923                         stream_fname,
6924                         nt_errstr(status));
6925                 goto out;
6926         }
6927         fnum1 = (uint16_t)-1;
6928
6929         /* POSIX unlink after stream handle closed should succeed. */
6930         status = cli_posix_unlink(cli2, fname);
6931         if (!NT_STATUS_IS_OK(status)) {
6932                 printf("cli_posix_unlink of %s failed (%s)\n",
6933                         fname,
6934                         nt_errstr(status));
6935                 goto out;
6936         }
6937
6938         printf("POSIX stream delete test passed\n");
6939         correct = true;
6940
6941   out:
6942
6943         if (fnum1 != (uint16_t)-1) {
6944                 cli_close(cli1, fnum1);
6945                 fnum1 = (uint16_t)-1;
6946         }
6947
6948         cli_setatr(cli1, fname, 0, 0);
6949         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6950
6951         if (!torture_close_connection(cli1)) {
6952                 correct = false;
6953         }
6954         if (!torture_close_connection(cli2)) {
6955                 correct = false;
6956         }
6957
6958         TALLOC_FREE(frame);
6959         return correct;
6960 }
6961
6962 /*
6963   Test setting EA's are rejected on symlinks.
6964  */
6965 static bool run_ea_symlink_test(int dummy)
6966 {
6967         static struct cli_state *cli;
6968         const char *fname = "posix_file_ea";
6969         const char *sname = "posix_symlink_ea";
6970         const char *ea_name = "testea_name";
6971         const char *ea_value = "testea_value";
6972         uint16_t fnum = (uint16_t)-1;
6973         bool correct = false;
6974         NTSTATUS status;
6975         size_t i, num_eas;
6976         struct ea_struct *eas = NULL;
6977         TALLOC_CTX *frame = NULL;
6978
6979         frame = talloc_stackframe();
6980
6981         printf("Starting EA symlink test\n");
6982
6983         if (!torture_open_connection(&cli, 0)) {
6984                 TALLOC_FREE(frame);
6985                 return false;
6986         }
6987
6988         smbXcli_conn_set_sockopt(cli->conn, sockops);
6989
6990         status = torture_setup_unix_extensions(cli);
6991         if (!NT_STATUS_IS_OK(status)) {
6992                 TALLOC_FREE(frame);
6993                 return false;
6994         }
6995
6996         cli_setatr(cli, fname, 0, 0);
6997         cli_posix_unlink(cli, fname);
6998         cli_setatr(cli, sname, 0, 0);
6999         cli_posix_unlink(cli, sname);
7000
7001         status = cli_ntcreate(cli,
7002                         fname,
7003                         0,
7004                         READ_CONTROL_ACCESS,
7005                         0,
7006                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7007                         FILE_CREATE,
7008                         0x0,
7009                         0x0,
7010                         &fnum,
7011                         NULL);
7012
7013         if (!NT_STATUS_IS_OK(status)) {
7014                 printf("cli_ntcreate of %s failed (%s)\n",
7015                         fname,
7016                         nt_errstr(status));
7017                 goto out;
7018         }
7019
7020         status = cli_close(cli, fnum);
7021         if (!NT_STATUS_IS_OK(status)) {
7022                 printf("close failed (%s)\n",
7023                         nt_errstr(status));
7024                 goto out;
7025         }
7026         fnum = (uint16_t)-1;
7027
7028         /* Set an EA on the path. */
7029         status = cli_set_ea_path(cli,
7030                                 fname,
7031                                 ea_name,
7032                                 ea_value,
7033                                 strlen(ea_value)+1);
7034
7035         if (!NT_STATUS_IS_OK(status)) {
7036                 printf("cli_set_ea_path failed (%s)\n",
7037                         nt_errstr(status));
7038                 goto out;
7039         }
7040
7041         /* Now create a symlink. */
7042         status = cli_posix_symlink(cli, fname, sname);
7043         if (!NT_STATUS_IS_OK(status)) {
7044                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
7045                         sname,
7046                         fname,
7047                         nt_errstr(status));
7048                 goto out;
7049         }
7050
7051         /* Get the EA list on the path. Should return value set. */
7052         status = cli_get_ea_list_path(cli,
7053                                 fname,
7054                                 frame,
7055                                 &num_eas,
7056                                 &eas);
7057
7058         if (!NT_STATUS_IS_OK(status)) {
7059                 printf("cli_get_ea_list_path failed (%s)\n",
7060                         nt_errstr(status));
7061                 goto out;
7062         }
7063
7064         /* Ensure the EA we set is there. */
7065         for (i=0; i<num_eas; i++) {
7066                 if (strcmp(eas[i].name, ea_name) == 0 &&
7067                                 eas[i].value.length == strlen(ea_value)+1 &&
7068                                 memcmp(eas[i].value.data,
7069                                         ea_value,
7070                                         eas[i].value.length) == 0) {
7071                         break;
7072                 }
7073         }
7074
7075         if (i == num_eas) {
7076                 printf("Didn't find EA on pathname %s\n",
7077                         fname);
7078                 goto out;
7079         }
7080
7081         num_eas = 0;
7082         TALLOC_FREE(eas);
7083
7084         /* Get the EA list on the symlink. Should return empty list. */
7085         status = cli_get_ea_list_path(cli,
7086                                 sname,
7087                                 frame,
7088                                 &num_eas,
7089                                 &eas);
7090
7091         if (!NT_STATUS_IS_OK(status)) {
7092                 printf("cli_get_ea_list_path failed (%s)\n",
7093                         nt_errstr(status));
7094                 goto out;
7095         }
7096
7097         if (num_eas != 0) {
7098                 printf("cli_get_ea_list_path failed (%s)\n",
7099                         nt_errstr(status));
7100                 goto out;
7101         }
7102
7103         /* Set an EA on the symlink. Should fail. */
7104         status = cli_set_ea_path(cli,
7105                                 sname,
7106                                 ea_name,
7107                                 ea_value,
7108                                 strlen(ea_value)+1);
7109
7110         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7111                 printf("cli_set_ea_path on a symlink gave %s. "
7112                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7113                         nt_errstr(status));
7114                 goto out;
7115         }
7116
7117         printf("EA symlink test passed\n");
7118         correct = true;
7119
7120   out:
7121
7122         if (fnum != (uint16_t)-1) {
7123                 cli_close(cli, fnum);
7124                 fnum = (uint16_t)-1;
7125         }
7126
7127         cli_setatr(cli, sname, 0, 0);
7128         cli_posix_unlink(cli, sname);
7129         cli_setatr(cli, fname, 0, 0);
7130         cli_posix_unlink(cli, fname);
7131
7132         if (!torture_close_connection(cli)) {
7133                 correct = false;
7134         }
7135
7136         TALLOC_FREE(frame);
7137         return correct;
7138 }
7139
7140 /*
7141   Test POSIX locks are OFD-locks.
7142  */
7143 static bool run_posix_ofd_lock_test(int dummy)
7144 {
7145         static struct cli_state *cli;
7146         const char *fname = "posix_file";
7147         uint16_t fnum1 = (uint16_t)-1;
7148         uint16_t fnum2 = (uint16_t)-1;
7149         bool correct = false;
7150         NTSTATUS status;
7151         TALLOC_CTX *frame = NULL;
7152
7153         frame = talloc_stackframe();
7154
7155         printf("Starting POSIX ofd-lock test\n");
7156
7157         if (!torture_open_connection(&cli, 0)) {
7158                 TALLOC_FREE(frame);
7159                 return false;
7160         }
7161
7162         smbXcli_conn_set_sockopt(cli->conn, sockops);
7163
7164         status = torture_setup_unix_extensions(cli);
7165         if (!NT_STATUS_IS_OK(status)) {
7166                 TALLOC_FREE(frame);
7167                 return false;
7168         }
7169
7170         cli_setatr(cli, fname, 0, 0);
7171         cli_posix_unlink(cli, fname);
7172
7173         /* Open the file twice. */
7174         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
7175                                 0600, &fnum1);
7176         if (!NT_STATUS_IS_OK(status)) {
7177                 printf("First POSIX open of %s failed\n", fname);
7178                 goto out;
7179         }
7180
7181         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
7182         if (!NT_STATUS_IS_OK(status)) {
7183                 printf("First POSIX open of %s failed\n", fname);
7184                 goto out;
7185         }
7186
7187         /* Set a 0-50 lock on fnum1. */
7188         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7189         if (!NT_STATUS_IS_OK(status)) {
7190                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
7191                 goto out;
7192         }
7193
7194         /* Set a 60-100 lock on fnum2. */
7195         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
7196         if (!NT_STATUS_IS_OK(status)) {
7197                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
7198                 goto out;
7199         }
7200
7201         /* close fnum1 - 0-50 lock should go away. */
7202         status = cli_close(cli, fnum1);
7203         if (!NT_STATUS_IS_OK(status)) {
7204                 printf("close failed (%s)\n",
7205                         nt_errstr(status));
7206                 goto out;
7207         }
7208         fnum1 = (uint16_t)-1;
7209
7210         /* Change the lock context. */
7211         cli_setpid(cli, cli_getpid(cli) + 1);
7212
7213         /* Re-open fnum1. */
7214         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7215         if (!NT_STATUS_IS_OK(status)) {
7216                 printf("Third POSIX open of %s failed\n", fname);
7217                 goto out;
7218         }
7219
7220         /* 60-100 lock should still be there. */
7221         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7222         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7223                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7224                 goto out;
7225         }
7226
7227         /* 0-50 lock should be gone. */
7228         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7229         if (!NT_STATUS_IS_OK(status)) {
7230                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7231                 goto out;
7232         }
7233
7234         printf("POSIX OFD lock test passed\n");
7235         correct = true;
7236
7237   out:
7238
7239         if (fnum1 != (uint16_t)-1) {
7240                 cli_close(cli, fnum1);
7241                 fnum1 = (uint16_t)-1;
7242         }
7243         if (fnum2 != (uint16_t)-1) {
7244                 cli_close(cli, fnum2);
7245                 fnum2 = (uint16_t)-1;
7246         }
7247
7248         cli_setatr(cli, fname, 0, 0);
7249         cli_posix_unlink(cli, fname);
7250
7251         if (!torture_close_connection(cli)) {
7252                 correct = false;
7253         }
7254
7255         TALLOC_FREE(frame);
7256         return correct;
7257 }
7258
7259 /*
7260   Test POSIX mkdir is case-sensitive.
7261  */
7262 static bool run_posix_mkdir_test(int dummy)
7263 {
7264         static struct cli_state *cli;
7265         const char *fname_foo = "POSIX_foo";
7266         const char *fname_foo_Foo = "POSIX_foo/Foo";
7267         const char *fname_foo_foo = "POSIX_foo/foo";
7268         const char *fname_Foo = "POSIX_Foo";
7269         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
7270         const char *fname_Foo_foo = "POSIX_Foo/foo";
7271         bool correct = false;
7272         NTSTATUS status;
7273         TALLOC_CTX *frame = NULL;
7274         uint16_t fnum = (uint16_t)-1;
7275
7276         frame = talloc_stackframe();
7277
7278         printf("Starting POSIX mkdir test\n");
7279
7280         if (!torture_open_connection(&cli, 0)) {
7281                 TALLOC_FREE(frame);
7282                 return false;
7283         }
7284
7285         smbXcli_conn_set_sockopt(cli->conn, sockops);
7286
7287         status = torture_setup_unix_extensions(cli);
7288         if (!NT_STATUS_IS_OK(status)) {
7289                 TALLOC_FREE(frame);
7290                 return false;
7291         }
7292
7293         cli_posix_rmdir(cli, fname_foo_foo);
7294         cli_posix_rmdir(cli, fname_foo_Foo);
7295         cli_posix_rmdir(cli, fname_foo);
7296
7297         cli_posix_rmdir(cli, fname_Foo_foo);
7298         cli_posix_rmdir(cli, fname_Foo_Foo);
7299         cli_posix_rmdir(cli, fname_Foo);
7300
7301         /*
7302          * Create a file POSIX_foo then try
7303          * and use it in a directory path by
7304          * doing mkdir POSIX_foo/bar.
7305          * The mkdir should fail with
7306          * NT_STATUS_OBJECT_PATH_NOT_FOUND
7307          */
7308
7309         status = cli_posix_open(cli,
7310                         fname_foo,
7311                         O_RDWR|O_CREAT,
7312                         0666,
7313                         &fnum);
7314         if (!NT_STATUS_IS_OK(status)) {
7315                 printf("cli_posix_open of %s failed error %s\n",
7316                         fname_foo,
7317                         nt_errstr(status));
7318                 goto out;
7319         }
7320
7321         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
7322         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7323                 printf("cli_posix_mkdir of %s should fail with "
7324                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7325                         "%s instead\n",
7326                         fname_foo_foo,
7327                         nt_errstr(status));
7328                 goto out;
7329         }
7330
7331         status = cli_close(cli, fnum);
7332         if (!NT_STATUS_IS_OK(status)) {
7333                 printf("cli_close failed %s\n", nt_errstr(status));
7334                 goto out;
7335         }
7336         fnum = (uint16_t)-1;
7337
7338         status = cli_posix_unlink(cli, fname_foo);
7339         if (!NT_STATUS_IS_OK(status)) {
7340                 printf("cli_posix_unlink of %s failed error %s\n",
7341                         fname_foo,
7342                         nt_errstr(status));
7343                 goto out;
7344         }
7345
7346         /*
7347          * Now we've deleted everything, posix_mkdir, posix_rmdir,
7348          * posix_open, posix_unlink, on
7349          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
7350          * not silently create POSIX_foo/foo.
7351          */
7352
7353         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
7354         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7355                 printf("cli_posix_mkdir of %s should fail with "
7356                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7357                         "%s instead\n",
7358                         fname_foo_foo,
7359                         nt_errstr(status));
7360                 goto out;
7361         }
7362
7363         status = cli_posix_rmdir(cli, fname_foo_foo);
7364         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7365                 printf("cli_posix_rmdir of %s should fail with "
7366                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7367                         "%s instead\n",
7368                         fname_foo_foo,
7369                         nt_errstr(status));
7370                 goto out;
7371         }
7372
7373         status = cli_posix_open(cli,
7374                         fname_foo_foo,
7375                         O_RDWR|O_CREAT,
7376                         0666,
7377                         &fnum);
7378         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7379                 printf("cli_posix_open of %s should fail with "
7380                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7381                         "%s instead\n",
7382                         fname_foo_foo,
7383                         nt_errstr(status));
7384                 goto out;
7385         }
7386
7387         status = cli_posix_unlink(cli, fname_foo_foo);
7388         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7389                 printf("cli_posix_unlink of %s should fail with "
7390                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7391                         "%s instead\n",
7392                         fname_foo_foo,
7393                         nt_errstr(status));
7394                 goto out;
7395         }
7396
7397         status = cli_posix_mkdir(cli, fname_foo, 0777);
7398         if (!NT_STATUS_IS_OK(status)) {
7399                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
7400                 goto out;
7401         }
7402
7403         status = cli_posix_mkdir(cli, fname_Foo, 0777);
7404         if (!NT_STATUS_IS_OK(status)) {
7405                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
7406                 goto out;
7407         }
7408
7409         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
7410         if (!NT_STATUS_IS_OK(status)) {
7411                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
7412                 goto out;
7413         }
7414
7415         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
7416         if (!NT_STATUS_IS_OK(status)) {
7417                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
7418                 goto out;
7419         }
7420
7421         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
7422         if (!NT_STATUS_IS_OK(status)) {
7423                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
7424                 goto out;
7425         }
7426
7427         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
7428         if (!NT_STATUS_IS_OK(status)) {
7429                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
7430                 goto out;
7431         }
7432
7433         printf("POSIX mkdir test passed\n");
7434         correct = true;
7435
7436   out:
7437
7438         if (fnum != (uint16_t)-1) {
7439                 cli_close(cli, fnum);
7440                 fnum = (uint16_t)-1;
7441         }
7442
7443         cli_posix_rmdir(cli, fname_foo_foo);
7444         cli_posix_rmdir(cli, fname_foo_Foo);
7445         cli_posix_rmdir(cli, fname_foo);
7446
7447         cli_posix_rmdir(cli, fname_Foo_foo);
7448         cli_posix_rmdir(cli, fname_Foo_Foo);
7449         cli_posix_rmdir(cli, fname_Foo);
7450
7451         if (!torture_close_connection(cli)) {
7452                 correct = false;
7453         }
7454
7455         TALLOC_FREE(frame);
7456         return correct;
7457 }
7458
7459
7460 static uint32_t open_attrs_table[] = {
7461                 FILE_ATTRIBUTE_NORMAL,
7462                 FILE_ATTRIBUTE_ARCHIVE,
7463                 FILE_ATTRIBUTE_READONLY,
7464                 FILE_ATTRIBUTE_HIDDEN,
7465                 FILE_ATTRIBUTE_SYSTEM,
7466
7467                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7468                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7469                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7470                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7471                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7472                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7473
7474                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7475                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7476                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7477                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7478 };
7479
7480 struct trunc_open_results {
7481         unsigned int num;
7482         uint32_t init_attr;
7483         uint32_t trunc_attr;
7484         uint32_t result_attr;
7485 };
7486
7487 static struct trunc_open_results attr_results[] = {
7488         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7489         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7490         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7491         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7492         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7493         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7494         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7495         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7496         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7497         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7498         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7499         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7500         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7501         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7502         { 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 },
7503         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7504         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7505         { 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 },
7506         { 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 },
7507         { 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 },
7508         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7509         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7510         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7511         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7512         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7513         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7514 };
7515
7516 static bool run_openattrtest(int dummy)
7517 {
7518         static struct cli_state *cli1;
7519         const char *fname = "\\openattr.file";
7520         uint16_t fnum1;
7521         bool correct = True;
7522         uint16_t attr;
7523         unsigned int i, j, k, l;
7524         NTSTATUS status;
7525
7526         printf("starting open attr test\n");
7527
7528         if (!torture_open_connection(&cli1, 0)) {
7529                 return False;
7530         }
7531
7532         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7533
7534         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7535                 cli_setatr(cli1, fname, 0, 0);
7536                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7537
7538                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7539                                        open_attrs_table[i], FILE_SHARE_NONE,
7540                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7541                 if (!NT_STATUS_IS_OK(status)) {
7542                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7543                         return False;
7544                 }
7545
7546                 status = cli_close(cli1, fnum1);
7547                 if (!NT_STATUS_IS_OK(status)) {
7548                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7549                         return False;
7550                 }
7551
7552                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7553                         status = cli_ntcreate(cli1, fname, 0,
7554                                               FILE_READ_DATA|FILE_WRITE_DATA,
7555                                               open_attrs_table[j],
7556                                               FILE_SHARE_NONE, FILE_OVERWRITE,
7557                                               0, 0, &fnum1, NULL);
7558                         if (!NT_STATUS_IS_OK(status)) {
7559                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7560                                         if (attr_results[l].num == k) {
7561                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7562                                                                 k, open_attrs_table[i],
7563                                                                 open_attrs_table[j],
7564                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
7565                                                 correct = False;
7566                                         }
7567                                 }
7568
7569                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7570                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7571                                                         k, open_attrs_table[i], open_attrs_table[j],
7572                                                         nt_errstr(status));
7573                                         correct = False;
7574                                 }
7575 #if 0
7576                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7577 #endif
7578                                 k++;
7579                                 continue;
7580                         }
7581
7582                         status = cli_close(cli1, fnum1);
7583                         if (!NT_STATUS_IS_OK(status)) {
7584                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7585                                 return False;
7586                         }
7587
7588                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7589                         if (!NT_STATUS_IS_OK(status)) {
7590                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7591                                 return False;
7592                         }
7593
7594 #if 0
7595                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7596                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
7597 #endif
7598
7599                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7600                                 if (attr_results[l].num == k) {
7601                                         if (attr != attr_results[l].result_attr ||
7602                                                         open_attrs_table[i] != attr_results[l].init_attr ||
7603                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
7604                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7605                                                 open_attrs_table[i],
7606                                                 open_attrs_table[j],
7607                                                 (unsigned int)attr,
7608                                                 attr_results[l].result_attr);
7609                                                 correct = False;
7610                                         }
7611                                         break;
7612                                 }
7613                         }
7614                         k++;
7615                 }
7616         }
7617
7618         cli_setatr(cli1, fname, 0, 0);
7619         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7620
7621         printf("open attr test %s.\n", correct ? "passed" : "failed");
7622
7623         if (!torture_close_connection(cli1)) {
7624                 correct = False;
7625         }
7626         return correct;
7627 }
7628
7629 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7630                     const char *name, void *state)
7631 {
7632         int *matched = (int *)state;
7633         if (matched != NULL) {
7634                 *matched += 1;
7635         }
7636         return NT_STATUS_OK;
7637 }
7638
7639 /*
7640   test directory listing speed
7641  */
7642 static bool run_dirtest(int dummy)
7643 {
7644         int i;
7645         static struct cli_state *cli;
7646         uint16_t fnum;
7647         struct timeval core_start;
7648         bool correct = True;
7649         int matched;
7650
7651         printf("starting directory test\n");
7652
7653         if (!torture_open_connection(&cli, 0)) {
7654                 return False;
7655         }
7656
7657         smbXcli_conn_set_sockopt(cli->conn, sockops);
7658
7659         srandom(0);
7660         for (i=0;i<torture_numops;i++) {
7661                 fstring fname;
7662                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7663                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7664                         fprintf(stderr,"Failed to open %s\n", fname);
7665                         return False;
7666                 }
7667                 cli_close(cli, fnum);
7668         }
7669
7670         core_start = timeval_current();
7671
7672         matched = 0;
7673         cli_list(cli, "a*.*", 0, list_fn, &matched);
7674         printf("Matched %d\n", matched);
7675
7676         matched = 0;
7677         cli_list(cli, "b*.*", 0, list_fn, &matched);
7678         printf("Matched %d\n", matched);
7679
7680         matched = 0;
7681         cli_list(cli, "xyzabc", 0, list_fn, &matched);
7682         printf("Matched %d\n", matched);
7683
7684         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7685
7686         srandom(0);
7687         for (i=0;i<torture_numops;i++) {
7688                 fstring fname;
7689                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7690                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7691         }
7692
7693         if (!torture_close_connection(cli)) {
7694                 correct = False;
7695         }
7696
7697         printf("finished dirtest\n");
7698
7699         return correct;
7700 }
7701
7702 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7703                    void *state)
7704 {
7705         struct cli_state *pcli = (struct cli_state *)state;
7706         fstring fname;
7707         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7708
7709         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7710                 return NT_STATUS_OK;
7711
7712         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7713                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7714                         printf("del_fn: failed to rmdir %s\n,", fname );
7715         } else {
7716                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7717                         printf("del_fn: failed to unlink %s\n,", fname );
7718         }
7719         return NT_STATUS_OK;
7720 }
7721
7722
7723 /*
7724   sees what IOCTLs are supported
7725  */
7726 bool torture_ioctl_test(int dummy)
7727 {
7728         static struct cli_state *cli;
7729         uint16_t device, function;
7730         uint16_t fnum;
7731         const char *fname = "\\ioctl.dat";
7732         DATA_BLOB blob;
7733         NTSTATUS status;
7734
7735         if (!torture_open_connection(&cli, 0)) {
7736                 return False;
7737         }
7738
7739         printf("starting ioctl test\n");
7740
7741         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7742
7743         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7744         if (!NT_STATUS_IS_OK(status)) {
7745                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7746                 return False;
7747         }
7748
7749         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7750         printf("ioctl device info: %s\n", nt_errstr(status));
7751
7752         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7753         printf("ioctl job info: %s\n", nt_errstr(status));
7754
7755         for (device=0;device<0x100;device++) {
7756                 printf("ioctl test with device = 0x%x\n", device);
7757                 for (function=0;function<0x100;function++) {
7758                         uint32_t code = (device<<16) | function;
7759
7760                         status = cli_raw_ioctl(cli, fnum, code, &blob);
7761
7762                         if (NT_STATUS_IS_OK(status)) {
7763                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7764                                        (int)blob.length);
7765                                 data_blob_free(&blob);
7766                         }
7767                 }
7768         }
7769
7770         if (!torture_close_connection(cli)) {
7771                 return False;
7772         }
7773
7774         return True;
7775 }
7776
7777
7778 /*
7779   tries varients of chkpath
7780  */
7781 bool torture_chkpath_test(int dummy)
7782 {
7783         static struct cli_state *cli;
7784         uint16_t fnum;
7785         bool ret;
7786         NTSTATUS status;
7787
7788         if (!torture_open_connection(&cli, 0)) {
7789                 return False;
7790         }
7791
7792         printf("starting chkpath test\n");
7793
7794         /* cleanup from an old run */
7795         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7796         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7797         cli_rmdir(cli, "\\chkpath.dir");
7798
7799         status = cli_mkdir(cli, "\\chkpath.dir");
7800         if (!NT_STATUS_IS_OK(status)) {
7801                 printf("mkdir1 failed : %s\n", nt_errstr(status));
7802                 return False;
7803         }
7804
7805         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7806         if (!NT_STATUS_IS_OK(status)) {
7807                 printf("mkdir2 failed : %s\n", nt_errstr(status));
7808                 return False;
7809         }
7810
7811         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7812                           DENY_NONE, &fnum);
7813         if (!NT_STATUS_IS_OK(status)) {
7814                 printf("open1 failed (%s)\n", nt_errstr(status));
7815                 return False;
7816         }
7817         cli_close(cli, fnum);
7818
7819         status = cli_chkpath(cli, "\\chkpath.dir");
7820         if (!NT_STATUS_IS_OK(status)) {
7821                 printf("chkpath1 failed: %s\n", nt_errstr(status));
7822                 ret = False;
7823         }
7824
7825         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7826         if (!NT_STATUS_IS_OK(status)) {
7827                 printf("chkpath2 failed: %s\n", nt_errstr(status));
7828                 ret = False;
7829         }
7830
7831         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7832         if (!NT_STATUS_IS_OK(status)) {
7833                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7834                                   NT_STATUS_NOT_A_DIRECTORY);
7835         } else {
7836                 printf("* chkpath on a file should fail\n");
7837                 ret = False;
7838         }
7839
7840         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7841         if (!NT_STATUS_IS_OK(status)) {
7842                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7843                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
7844         } else {
7845                 printf("* chkpath on a non existent file should fail\n");
7846                 ret = False;
7847         }
7848
7849         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7850         if (!NT_STATUS_IS_OK(status)) {
7851                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7852                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
7853         } else {
7854                 printf("* chkpath on a non existent component should fail\n");
7855                 ret = False;
7856         }
7857
7858         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7859         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7860         cli_rmdir(cli, "\\chkpath.dir");
7861
7862         if (!torture_close_connection(cli)) {
7863                 return False;
7864         }
7865
7866         return ret;
7867 }
7868
7869 static bool run_eatest(int dummy)
7870 {
7871         static struct cli_state *cli;
7872         const char *fname = "\\eatest.txt";
7873         bool correct = True;
7874         uint16_t fnum;
7875         int i;
7876         size_t num_eas;
7877         struct ea_struct *ea_list = NULL;
7878         TALLOC_CTX *mem_ctx = talloc_init("eatest");
7879         NTSTATUS status;
7880
7881         printf("starting eatest\n");
7882
7883         if (!torture_open_connection(&cli, 0)) {
7884                 talloc_destroy(mem_ctx);
7885                 return False;
7886         }
7887
7888         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7889
7890         status = cli_ntcreate(cli, fname, 0,
7891                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7892                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7893                               0x4044, 0, &fnum, NULL);
7894         if (!NT_STATUS_IS_OK(status)) {
7895                 printf("open failed - %s\n", nt_errstr(status));
7896                 talloc_destroy(mem_ctx);
7897                 return False;
7898         }
7899
7900         for (i = 0; i < 10; i++) {
7901                 fstring ea_name, ea_val;
7902
7903                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7904                 memset(ea_val, (char)i+1, i+1);
7905                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7906                 if (!NT_STATUS_IS_OK(status)) {
7907                         printf("ea_set of name %s failed - %s\n", ea_name,
7908                                nt_errstr(status));
7909                         talloc_destroy(mem_ctx);
7910                         return False;
7911                 }
7912         }
7913
7914         cli_close(cli, fnum);
7915         for (i = 0; i < 10; i++) {
7916                 fstring ea_name, ea_val;
7917
7918                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7919                 memset(ea_val, (char)i+1, i+1);
7920                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7921                 if (!NT_STATUS_IS_OK(status)) {
7922                         printf("ea_set of name %s failed - %s\n", ea_name,
7923                                nt_errstr(status));
7924                         talloc_destroy(mem_ctx);
7925                         return False;
7926                 }
7927         }
7928
7929         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7930         if (!NT_STATUS_IS_OK(status)) {
7931                 printf("ea_get list failed - %s\n", nt_errstr(status));
7932                 correct = False;
7933         }
7934
7935         printf("num_eas = %d\n", (int)num_eas);
7936
7937         if (num_eas != 20) {
7938                 printf("Should be 20 EA's stored... failing.\n");
7939                 correct = False;
7940         }
7941
7942         for (i = 0; i < num_eas; i++) {
7943                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7944                 dump_data(0, ea_list[i].value.data,
7945                           ea_list[i].value.length);
7946         }
7947
7948         /* Setting EA's to zero length deletes them. Test this */
7949         printf("Now deleting all EA's - case indepenent....\n");
7950
7951 #if 1
7952         cli_set_ea_path(cli, fname, "", "", 0);
7953 #else
7954         for (i = 0; i < 20; i++) {
7955                 fstring ea_name;
7956                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7957                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7958                 if (!NT_STATUS_IS_OK(status)) {
7959                         printf("ea_set of name %s failed - %s\n", ea_name,
7960                                nt_errstr(status));
7961                         talloc_destroy(mem_ctx);
7962                         return False;
7963                 }
7964         }
7965 #endif
7966
7967         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7968         if (!NT_STATUS_IS_OK(status)) {
7969                 printf("ea_get list failed - %s\n", nt_errstr(status));
7970                 correct = False;
7971         }
7972
7973         printf("num_eas = %d\n", (int)num_eas);
7974         for (i = 0; i < num_eas; i++) {
7975                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7976                 dump_data(0, ea_list[i].value.data,
7977                           ea_list[i].value.length);
7978         }
7979
7980         if (num_eas != 0) {
7981                 printf("deleting EA's failed.\n");
7982                 correct = False;
7983         }
7984
7985         /* Try and delete a non existent EA. */
7986         status = cli_set_ea_path(cli, fname, "foo", "", 0);
7987         if (!NT_STATUS_IS_OK(status)) {
7988                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7989                        nt_errstr(status));
7990                 correct = False;
7991         }
7992
7993         talloc_destroy(mem_ctx);
7994         if (!torture_close_connection(cli)) {
7995                 correct = False;
7996         }
7997
7998         return correct;
7999 }
8000
8001 static bool run_dirtest1(int dummy)
8002 {
8003         int i;
8004         static struct cli_state *cli;
8005         uint16_t fnum;
8006         int num_seen;
8007         bool correct = True;
8008
8009         printf("starting directory test\n");
8010
8011         if (!torture_open_connection(&cli, 0)) {
8012                 return False;
8013         }
8014
8015         smbXcli_conn_set_sockopt(cli->conn, sockops);
8016
8017         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
8018         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
8019         cli_rmdir(cli, "\\LISTDIR");
8020         cli_mkdir(cli, "\\LISTDIR");
8021
8022         /* Create 1000 files and 1000 directories. */
8023         for (i=0;i<1000;i++) {
8024                 fstring fname;
8025                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
8026                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
8027                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
8028                                    0, 0, &fnum, NULL))) {
8029                         fprintf(stderr,"Failed to open %s\n", fname);
8030                         return False;
8031                 }
8032                 cli_close(cli, fnum);
8033         }
8034         for (i=0;i<1000;i++) {
8035                 fstring fname;
8036                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
8037                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
8038                         fprintf(stderr,"Failed to open %s\n", fname);
8039                         return False;
8040                 }
8041         }
8042
8043         /* Now ensure that doing an old list sees both files and directories. */
8044         num_seen = 0;
8045         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
8046         printf("num_seen = %d\n", num_seen );
8047         /* We should see 100 files + 1000 directories + . and .. */
8048         if (num_seen != 2002)
8049                 correct = False;
8050
8051         /* Ensure if we have the "must have" bits we only see the
8052          * relevent entries.
8053          */
8054         num_seen = 0;
8055         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
8056         printf("num_seen = %d\n", num_seen );
8057         if (num_seen != 1002)
8058                 correct = False;
8059
8060         num_seen = 0;
8061         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
8062         printf("num_seen = %d\n", num_seen );
8063         if (num_seen != 1000)
8064                 correct = False;
8065
8066         /* Delete everything. */
8067         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
8068         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
8069         cli_rmdir(cli, "\\LISTDIR");
8070
8071 #if 0
8072         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
8073         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
8074         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
8075 #endif
8076
8077         if (!torture_close_connection(cli)) {
8078                 correct = False;
8079         }
8080
8081         printf("finished dirtest1\n");
8082
8083         return correct;
8084 }
8085
8086 static bool run_error_map_extract(int dummy) {
8087
8088         static struct cli_state *c_dos;
8089         static struct cli_state *c_nt;
8090         NTSTATUS status;
8091
8092         uint32_t error;
8093
8094         uint32_t errnum;
8095         uint8_t errclass;
8096
8097         NTSTATUS nt_status;
8098
8099         fstring user;
8100
8101         /* NT-Error connection */
8102
8103         disable_spnego = true;
8104         if (!(c_nt = open_nbt_connection())) {
8105                 disable_spnego = false;
8106                 return False;
8107         }
8108         disable_spnego = false;
8109
8110         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
8111                                  PROTOCOL_NT1);
8112
8113         if (!NT_STATUS_IS_OK(status)) {
8114                 printf("%s rejected the NT-error negprot (%s)\n", host,
8115                        nt_errstr(status));
8116                 cli_shutdown(c_nt);
8117                 return False;
8118         }
8119
8120         status = cli_session_setup_anon(c_nt);
8121         if (!NT_STATUS_IS_OK(status)) {
8122                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
8123                 return False;
8124         }
8125
8126         /* DOS-Error connection */
8127
8128         disable_spnego = true;
8129         force_dos_errors = true;
8130         if (!(c_dos = open_nbt_connection())) {
8131                 disable_spnego = false;
8132                 force_dos_errors = false;
8133                 return False;
8134         }
8135         disable_spnego = false;
8136         force_dos_errors = false;
8137
8138         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
8139                                  PROTOCOL_NT1);
8140         if (!NT_STATUS_IS_OK(status)) {
8141                 printf("%s rejected the DOS-error negprot (%s)\n", host,
8142                        nt_errstr(status));
8143                 cli_shutdown(c_dos);
8144                 return False;
8145         }
8146
8147         status = cli_session_setup_anon(c_dos);
8148         if (!NT_STATUS_IS_OK(status)) {
8149                 printf("%s rejected the DOS-error initial session setup (%s)\n",
8150                         host, nt_errstr(status));
8151                 return False;
8152         }
8153
8154         c_nt->map_dos_errors = false;
8155         c_dos->map_dos_errors = false;
8156
8157         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
8158                 struct cli_credentials *user_creds = NULL;
8159
8160                 fstr_sprintf(user, "%X", error);
8161
8162                 user_creds = cli_session_creds_init(talloc_tos(),
8163                                                     user,
8164                                                     workgroup,
8165                                                     NULL, /* realm */
8166                                                     password,
8167                                                     false, /* use_kerberos */
8168                                                     false, /* fallback_after_kerberos */
8169                                                     false, /* use_ccache */
8170                                                     false); /* password_is_nt_hash */
8171                 if (user_creds == NULL) {
8172                         printf("cli_session_creds_init(%s) failed\n", user);
8173                         return false;
8174                 }
8175
8176                 status = cli_session_setup_creds(c_nt, user_creds);
8177                 if (NT_STATUS_IS_OK(status)) {
8178                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
8179                 }
8180
8181                 /* Case #1: 32-bit NT errors */
8182                 if (!NT_STATUS_IS_DOS(status)) {
8183                         nt_status = status;
8184                 } else {
8185                         printf("/** Dos error on NT connection! (%s) */\n", 
8186                                nt_errstr(status));
8187                         nt_status = NT_STATUS(0xc0000000);
8188                 }
8189
8190                 status = cli_session_setup_creds(c_dos, user_creds);
8191                 if (NT_STATUS_IS_OK(status)) {
8192                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
8193                 }
8194
8195                 /* Case #1: 32-bit NT errors */
8196                 if (NT_STATUS_IS_DOS(status)) {
8197                         printf("/** NT error on DOS connection! (%s) */\n", 
8198                                nt_errstr(status));
8199                         errnum = errclass = 0;
8200                 } else {
8201                         errclass = NT_STATUS_DOS_CLASS(status);
8202                         errnum = NT_STATUS_DOS_CODE(status);
8203                 }
8204
8205                 if (NT_STATUS_V(nt_status) != error) { 
8206                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
8207                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
8208                                get_nt_error_c_code(talloc_tos(), nt_status));
8209                 }
8210
8211                 printf("\t{%s,\t%s,\t%s},\n", 
8212                        smb_dos_err_class(errclass), 
8213                        smb_dos_err_name(errclass, errnum), 
8214                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
8215
8216                 TALLOC_FREE(user_creds);
8217         }
8218         return True;
8219 }
8220
8221 static bool run_sesssetup_bench(int dummy)
8222 {
8223         static struct cli_state *c;
8224         const char *fname = "\\file.dat";
8225         uint16_t fnum;
8226         NTSTATUS status;
8227         int i;
8228
8229         if (!torture_open_connection(&c, 0)) {
8230                 return false;
8231         }
8232
8233         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8234                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8235                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
8236         if (!NT_STATUS_IS_OK(status)) {
8237                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8238                 return false;
8239         }
8240
8241         for (i=0; i<torture_numops; i++) {
8242                 status = cli_session_setup_creds(c, torture_creds);
8243                 if (!NT_STATUS_IS_OK(status)) {
8244                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
8245                                  __location__, nt_errstr(status));
8246                         return false;
8247                 }
8248
8249                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
8250
8251                 status = cli_ulogoff(c);
8252                 if (!NT_STATUS_IS_OK(status)) {
8253                         d_printf("(%s) cli_ulogoff failed: %s\n",
8254                                  __location__, nt_errstr(status));
8255                         return false;
8256                 }
8257         }
8258
8259         return true;
8260 }
8261
8262 static bool subst_test(const char *str, const char *user, const char *domain,
8263                        uid_t uid, gid_t gid, const char *expected)
8264 {
8265         char *subst;
8266         bool result = true;
8267
8268         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
8269
8270         if (strcmp(subst, expected) != 0) {
8271                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
8272                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
8273                        expected);
8274                 result = false;
8275         }
8276
8277         TALLOC_FREE(subst);
8278         return result;
8279 }
8280
8281 static void chain1_open_completion(struct tevent_req *req)
8282 {
8283         uint16_t fnum;
8284         NTSTATUS status;
8285         status = cli_openx_recv(req, &fnum);
8286         TALLOC_FREE(req);
8287
8288         d_printf("cli_openx_recv returned %s: %d\n",
8289                  nt_errstr(status),
8290                  NT_STATUS_IS_OK(status) ? fnum : -1);
8291 }
8292
8293 static void chain1_write_completion(struct tevent_req *req)
8294 {
8295         size_t written;
8296         NTSTATUS status;
8297         status = cli_write_andx_recv(req, &written);
8298         TALLOC_FREE(req);
8299
8300         d_printf("cli_write_andx_recv returned %s: %d\n",
8301                  nt_errstr(status),
8302                  NT_STATUS_IS_OK(status) ? (int)written : -1);
8303 }
8304
8305 static void chain1_close_completion(struct tevent_req *req)
8306 {
8307         NTSTATUS status;
8308         bool *done = (bool *)tevent_req_callback_data_void(req);
8309
8310         status = cli_close_recv(req);
8311         *done = true;
8312
8313         TALLOC_FREE(req);
8314
8315         d_printf("cli_close returned %s\n", nt_errstr(status));
8316 }
8317
8318 static bool run_chain1(int dummy)
8319 {
8320         struct cli_state *cli1;
8321         struct tevent_context *evt = samba_tevent_context_init(NULL);
8322         struct tevent_req *reqs[3], *smbreqs[3];
8323         bool done = false;
8324         const char *str = "foobar";
8325         const char *fname = "\\test_chain";
8326         NTSTATUS status;
8327
8328         printf("starting chain1 test\n");
8329         if (!torture_open_connection(&cli1, 0)) {
8330                 return False;
8331         }
8332
8333         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8334
8335         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8336
8337         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
8338                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
8339         if (reqs[0] == NULL) return false;
8340         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
8341
8342
8343         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
8344                                         (const uint8_t *)str, 0, strlen(str)+1,
8345                                         smbreqs, 1, &smbreqs[1]);
8346         if (reqs[1] == NULL) return false;
8347         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
8348
8349         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
8350         if (reqs[2] == NULL) return false;
8351         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
8352
8353         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8354         if (!NT_STATUS_IS_OK(status)) {
8355                 return false;
8356         }
8357
8358         while (!done) {
8359                 tevent_loop_once(evt);
8360         }
8361
8362         torture_close_connection(cli1);
8363         return True;
8364 }
8365
8366 static void chain2_sesssetup_completion(struct tevent_req *req)
8367 {
8368         NTSTATUS status;
8369         status = cli_session_setup_guest_recv(req);
8370         d_printf("sesssetup returned %s\n", nt_errstr(status));
8371 }
8372
8373 static void chain2_tcon_completion(struct tevent_req *req)
8374 {
8375         bool *done = (bool *)tevent_req_callback_data_void(req);
8376         NTSTATUS status;
8377         status = cli_tcon_andx_recv(req);
8378         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
8379         *done = true;
8380 }
8381
8382 static bool run_chain2(int dummy)
8383 {
8384         struct cli_state *cli1;
8385         struct tevent_context *evt = samba_tevent_context_init(NULL);
8386         struct tevent_req *reqs[2], *smbreqs[2];
8387         bool done = false;
8388         NTSTATUS status;
8389         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
8390
8391         printf("starting chain2 test\n");
8392         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
8393                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
8394         if (!NT_STATUS_IS_OK(status)) {
8395                 return False;
8396         }
8397
8398         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8399
8400         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
8401                                                  &smbreqs[0]);
8402         if (reqs[0] == NULL) return false;
8403         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
8404
8405         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
8406                                        "?????", NULL, 0, &smbreqs[1]);
8407         if (reqs[1] == NULL) return false;
8408         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
8409
8410         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8411         if (!NT_STATUS_IS_OK(status)) {
8412                 return false;
8413         }
8414
8415         while (!done) {
8416                 tevent_loop_once(evt);
8417         }
8418
8419         torture_close_connection(cli1);
8420         return True;
8421 }
8422
8423
8424 struct torture_createdel_state {
8425         struct tevent_context *ev;
8426         struct cli_state *cli;
8427 };
8428
8429 static void torture_createdel_created(struct tevent_req *subreq);
8430 static void torture_createdel_closed(struct tevent_req *subreq);
8431
8432 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8433                                                  struct tevent_context *ev,
8434                                                  struct cli_state *cli,
8435                                                  const char *name)
8436 {
8437         struct tevent_req *req, *subreq;
8438         struct torture_createdel_state *state;
8439
8440         req = tevent_req_create(mem_ctx, &state,
8441                                 struct torture_createdel_state);
8442         if (req == NULL) {
8443                 return NULL;
8444         }
8445         state->ev = ev;
8446         state->cli = cli;
8447
8448         subreq = cli_ntcreate_send(
8449                 state, ev, cli, name, 0,
8450                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8451                 FILE_ATTRIBUTE_NORMAL,
8452                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8453                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
8454                 SMB2_IMPERSONATION_IMPERSONATION, 0);
8455
8456         if (tevent_req_nomem(subreq, req)) {
8457                 return tevent_req_post(req, ev);
8458         }
8459         tevent_req_set_callback(subreq, torture_createdel_created, req);
8460         return req;
8461 }
8462
8463 static void torture_createdel_created(struct tevent_req *subreq)
8464 {
8465         struct tevent_req *req = tevent_req_callback_data(
8466                 subreq, struct tevent_req);
8467         struct torture_createdel_state *state = tevent_req_data(
8468                 req, struct torture_createdel_state);
8469         NTSTATUS status;
8470         uint16_t fnum;
8471
8472         status = cli_ntcreate_recv(subreq, &fnum, NULL);
8473         TALLOC_FREE(subreq);
8474         if (tevent_req_nterror(req, status)) {
8475                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8476                            nt_errstr(status)));
8477                 return;
8478         }
8479
8480         subreq = cli_close_send(state, state->ev, state->cli, fnum);
8481         if (tevent_req_nomem(subreq, req)) {
8482                 return;
8483         }
8484         tevent_req_set_callback(subreq, torture_createdel_closed, req);
8485 }
8486
8487 static void torture_createdel_closed(struct tevent_req *subreq)
8488 {
8489         struct tevent_req *req = tevent_req_callback_data(
8490                 subreq, struct tevent_req);
8491         NTSTATUS status;
8492
8493         status = cli_close_recv(subreq);
8494         if (tevent_req_nterror(req, status)) {
8495                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8496                 return;
8497         }
8498         tevent_req_done(req);
8499 }
8500
8501 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8502 {
8503         return tevent_req_simple_recv_ntstatus(req);
8504 }
8505
8506 struct torture_createdels_state {
8507         struct tevent_context *ev;
8508         struct cli_state *cli;
8509         const char *base_name;
8510         int sent;
8511         int received;
8512         int num_files;
8513         struct tevent_req **reqs;
8514 };
8515
8516 static void torture_createdels_done(struct tevent_req *subreq);
8517
8518 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8519                                                   struct tevent_context *ev,
8520                                                   struct cli_state *cli,
8521                                                   const char *base_name,
8522                                                   int num_parallel,
8523                                                   int num_files)
8524 {
8525         struct tevent_req *req;
8526         struct torture_createdels_state *state;
8527         int i;
8528
8529         req = tevent_req_create(mem_ctx, &state,
8530                                 struct torture_createdels_state);
8531         if (req == NULL) {
8532                 return NULL;
8533         }
8534         state->ev = ev;
8535         state->cli = cli;
8536         state->base_name = talloc_strdup(state, base_name);
8537         if (tevent_req_nomem(state->base_name, req)) {
8538                 return tevent_req_post(req, ev);
8539         }
8540         state->num_files = MAX(num_parallel, num_files);
8541         state->sent = 0;
8542         state->received = 0;
8543
8544         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8545         if (tevent_req_nomem(state->reqs, req)) {
8546                 return tevent_req_post(req, ev);
8547         }
8548
8549         for (i=0; i<num_parallel; i++) {
8550                 char *name;
8551
8552                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8553                                        state->sent);
8554                 if (tevent_req_nomem(name, req)) {
8555                         return tevent_req_post(req, ev);
8556                 }
8557                 state->reqs[i] = torture_createdel_send(
8558                         state->reqs, state->ev, state->cli, name);
8559                 if (tevent_req_nomem(state->reqs[i], req)) {
8560                         return tevent_req_post(req, ev);
8561                 }
8562                 name = talloc_move(state->reqs[i], &name);
8563                 tevent_req_set_callback(state->reqs[i],
8564                                         torture_createdels_done, req);
8565                 state->sent += 1;
8566         }
8567         return req;
8568 }
8569
8570 static void torture_createdels_done(struct tevent_req *subreq)
8571 {
8572         struct tevent_req *req = tevent_req_callback_data(
8573                 subreq, struct tevent_req);
8574         struct torture_createdels_state *state = tevent_req_data(
8575                 req, struct torture_createdels_state);
8576         size_t num_parallel = talloc_array_length(state->reqs);
8577         NTSTATUS status;
8578         char *name;
8579         int i;
8580
8581         status = torture_createdel_recv(subreq);
8582         if (!NT_STATUS_IS_OK(status)){
8583                 DEBUG(10, ("torture_createdel_recv returned %s\n",
8584                            nt_errstr(status)));
8585                 TALLOC_FREE(subreq);
8586                 tevent_req_nterror(req, status);
8587                 return;
8588         }
8589
8590         for (i=0; i<num_parallel; i++) {
8591                 if (subreq == state->reqs[i]) {
8592                         break;
8593                 }
8594         }
8595         if (i == num_parallel) {
8596                 DEBUG(10, ("received something we did not send\n"));
8597                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8598                 return;
8599         }
8600         TALLOC_FREE(state->reqs[i]);
8601
8602         if (state->sent >= state->num_files) {
8603                 tevent_req_done(req);
8604                 return;
8605         }
8606
8607         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8608                                state->sent);
8609         if (tevent_req_nomem(name, req)) {
8610                 return;
8611         }
8612         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8613                                                 state->cli, name);
8614         if (tevent_req_nomem(state->reqs[i], req)) {
8615                 return;
8616         }
8617         name = talloc_move(state->reqs[i], &name);
8618         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8619         state->sent += 1;
8620 }
8621
8622 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8623 {
8624         return tevent_req_simple_recv_ntstatus(req);
8625 }
8626
8627 struct swallow_notify_state {
8628         struct tevent_context *ev;
8629         struct cli_state *cli;
8630         uint16_t fnum;
8631         uint32_t completion_filter;
8632         bool recursive;
8633         bool (*fn)(uint32_t action, const char *name, void *priv);
8634         void *priv;
8635 };
8636
8637 static void swallow_notify_done(struct tevent_req *subreq);
8638
8639 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8640                                               struct tevent_context *ev,
8641                                               struct cli_state *cli,
8642                                               uint16_t fnum,
8643                                               uint32_t completion_filter,
8644                                               bool recursive,
8645                                               bool (*fn)(uint32_t action,
8646                                                          const char *name,
8647                                                          void *priv),
8648                                               void *priv)
8649 {
8650         struct tevent_req *req, *subreq;
8651         struct swallow_notify_state *state;
8652
8653         req = tevent_req_create(mem_ctx, &state,
8654                                 struct swallow_notify_state);
8655         if (req == NULL) {
8656                 return NULL;
8657         }
8658         state->ev = ev;
8659         state->cli = cli;
8660         state->fnum = fnum;
8661         state->completion_filter = completion_filter;
8662         state->recursive = recursive;
8663         state->fn = fn;
8664         state->priv = priv;
8665
8666         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8667                                  0xffff, state->completion_filter,
8668                                  state->recursive);
8669         if (tevent_req_nomem(subreq, req)) {
8670                 return tevent_req_post(req, ev);
8671         }
8672         tevent_req_set_callback(subreq, swallow_notify_done, req);
8673         return req;
8674 }
8675
8676 static void swallow_notify_done(struct tevent_req *subreq)
8677 {
8678         struct tevent_req *req = tevent_req_callback_data(
8679                 subreq, struct tevent_req);
8680         struct swallow_notify_state *state = tevent_req_data(
8681                 req, struct swallow_notify_state);
8682         NTSTATUS status;
8683         uint32_t i, num_changes;
8684         struct notify_change *changes;
8685
8686         status = cli_notify_recv(subreq, state, &num_changes, &changes);
8687         TALLOC_FREE(subreq);
8688         if (!NT_STATUS_IS_OK(status)) {
8689                 DEBUG(10, ("cli_notify_recv returned %s\n",
8690                            nt_errstr(status)));
8691                 tevent_req_nterror(req, status);
8692                 return;
8693         }
8694
8695         for (i=0; i<num_changes; i++) {
8696                 state->fn(changes[i].action, changes[i].name, state->priv);
8697         }
8698         TALLOC_FREE(changes);
8699
8700         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8701                                  0xffff, state->completion_filter,
8702                                  state->recursive);
8703         if (tevent_req_nomem(subreq, req)) {
8704                 return;
8705         }
8706         tevent_req_set_callback(subreq, swallow_notify_done, req);
8707 }
8708
8709 static bool print_notifies(uint32_t action, const char *name, void *priv)
8710 {
8711         if (DEBUGLEVEL > 5) {
8712                 d_printf("%d %s\n", (int)action, name);
8713         }
8714         return true;
8715 }
8716
8717 static void notify_bench_done(struct tevent_req *req)
8718 {
8719         int *num_finished = (int *)tevent_req_callback_data_void(req);
8720         *num_finished += 1;
8721 }
8722
8723 static bool run_notify_bench(int dummy)
8724 {
8725         const char *dname = "\\notify-bench";
8726         struct tevent_context *ev;
8727         NTSTATUS status;
8728         uint16_t dnum;
8729         struct tevent_req *req1;
8730         struct tevent_req *req2 = NULL;
8731         int i, num_unc_names;
8732         int num_finished = 0;
8733
8734         printf("starting notify-bench test\n");
8735
8736         if (use_multishare_conn) {
8737                 char **unc_list;
8738                 unc_list = file_lines_load(multishare_conn_fname,
8739                                            &num_unc_names, 0, NULL);
8740                 if (!unc_list || num_unc_names <= 0) {
8741                         d_printf("Failed to load unc names list from '%s'\n",
8742                                  multishare_conn_fname);
8743                         return false;
8744                 }
8745                 TALLOC_FREE(unc_list);
8746         } else {
8747                 num_unc_names = 1;
8748         }
8749
8750         ev = samba_tevent_context_init(talloc_tos());
8751         if (ev == NULL) {
8752                 d_printf("tevent_context_init failed\n");
8753                 return false;
8754         }
8755
8756         for (i=0; i<num_unc_names; i++) {
8757                 struct cli_state *cli;
8758                 char *base_fname;
8759
8760                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8761                                              dname, i);
8762                 if (base_fname == NULL) {
8763                         return false;
8764                 }
8765
8766                 if (!torture_open_connection(&cli, i)) {
8767                         return false;
8768                 }
8769
8770                 status = cli_ntcreate(cli, dname, 0,
8771                                       MAXIMUM_ALLOWED_ACCESS,
8772                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8773                                       FILE_SHARE_DELETE,
8774                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8775                                       &dnum, NULL);
8776
8777                 if (!NT_STATUS_IS_OK(status)) {
8778                         d_printf("Could not create %s: %s\n", dname,
8779                                  nt_errstr(status));
8780                         return false;
8781                 }
8782
8783                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8784                                            FILE_NOTIFY_CHANGE_FILE_NAME |
8785                                            FILE_NOTIFY_CHANGE_DIR_NAME |
8786                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
8787                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
8788                                            false, print_notifies, NULL);
8789                 if (req1 == NULL) {
8790                         d_printf("Could not create notify request\n");
8791                         return false;
8792                 }
8793
8794                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8795                                                base_fname, 10, torture_numops);
8796                 if (req2 == NULL) {
8797                         d_printf("Could not create createdels request\n");
8798                         return false;
8799                 }
8800                 TALLOC_FREE(base_fname);
8801
8802                 tevent_req_set_callback(req2, notify_bench_done,
8803                                         &num_finished);
8804         }
8805
8806         while (num_finished < num_unc_names) {
8807                 int ret;
8808                 ret = tevent_loop_once(ev);
8809                 if (ret != 0) {
8810                         d_printf("tevent_loop_once failed\n");
8811                         return false;
8812                 }
8813         }
8814
8815         if (!tevent_req_poll(req2, ev)) {
8816                 d_printf("tevent_req_poll failed\n");
8817         }
8818
8819         status = torture_createdels_recv(req2);
8820         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8821
8822         return true;
8823 }
8824
8825 static bool run_mangle1(int dummy)
8826 {
8827         struct cli_state *cli;
8828         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8829         uint16_t fnum;
8830         fstring alt_name;
8831         NTSTATUS status;
8832         time_t change_time, access_time, write_time;
8833         off_t size;
8834         uint16_t mode;
8835
8836         printf("starting mangle1 test\n");
8837         if (!torture_open_connection(&cli, 0)) {
8838                 return False;
8839         }
8840
8841         smbXcli_conn_set_sockopt(cli->conn, sockops);
8842
8843         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8844                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8845                               0, 0, &fnum, NULL);
8846         if (!NT_STATUS_IS_OK(status)) {
8847                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8848                 return false;
8849         }
8850         cli_close(cli, fnum);
8851
8852         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8853         if (!NT_STATUS_IS_OK(status)) {
8854                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8855                          nt_errstr(status));
8856                 return false;
8857         }
8858         d_printf("alt_name: %s\n", alt_name);
8859
8860         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8861         if (!NT_STATUS_IS_OK(status)) {
8862                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8863                          nt_errstr(status));
8864                 return false;
8865         }
8866         cli_close(cli, fnum);
8867
8868         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8869                                 &write_time, &size, &mode);
8870         if (!NT_STATUS_IS_OK(status)) {
8871                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8872                          nt_errstr(status));
8873                 return false;
8874         }
8875
8876         return true;
8877 }
8878
8879 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8880                                                  struct file_info *f,
8881                                                  const char *mask,
8882                                                  void *state)
8883 {
8884         if (f->short_name == NULL) {
8885                 return NT_STATUS_OK;
8886         }
8887
8888         if (strlen(f->short_name) == 0) {
8889                 return NT_STATUS_OK;
8890         }
8891
8892         printf("unexpected shortname: %s\n", f->short_name);
8893
8894         return NT_STATUS_OBJECT_NAME_INVALID;
8895 }
8896
8897 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8898                                             struct file_info *f,
8899                                             const char *mask,
8900                                             void *state)
8901 {
8902         char *name = state;
8903
8904         printf("name: %s\n", f->name);
8905         fstrcpy(name, f->name);
8906         return NT_STATUS_OK;
8907 }
8908
8909 static bool run_mangle_illegal(int dummy)
8910 {
8911         struct cli_state *cli = NULL;
8912         struct cli_state *cli_posix = NULL;
8913         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8914         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8915         char *mangled_path = NULL;
8916         uint16_t fnum;
8917         fstring name;
8918         fstring alt_name;
8919         NTSTATUS status;
8920
8921         printf("starting mangle-illegal test\n");
8922
8923         if (!torture_open_connection(&cli, 0)) {
8924                 return False;
8925         }
8926
8927         smbXcli_conn_set_sockopt(cli->conn, sockops);
8928
8929         if (!torture_open_connection(&cli_posix, 0)) {
8930                 return false;
8931         }
8932
8933         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8934
8935         status = torture_setup_unix_extensions(cli_posix);
8936         if (!NT_STATUS_IS_OK(status)) {
8937                 return false;
8938         }
8939
8940         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8941         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8942         if (!NT_STATUS_IS_OK(status)) {
8943                 printf("mkdir1 failed : %s\n", nt_errstr(status));
8944                 return False;
8945         }
8946
8947         /*
8948          * Create a file with illegal NTFS characters and test that we
8949          * get a usable mangled name
8950          */
8951
8952         cli_setatr(cli_posix, illegal_fname, 0, 0);
8953         cli_posix_unlink(cli_posix, illegal_fname);
8954
8955         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8956                                 0600, &fnum);
8957         if (!NT_STATUS_IS_OK(status)) {
8958                 printf("POSIX create of %s failed (%s)\n",
8959                        illegal_fname, nt_errstr(status));
8960                 return false;
8961         }
8962
8963         status = cli_close(cli_posix, fnum);
8964         if (!NT_STATUS_IS_OK(status)) {
8965                 printf("close failed (%s)\n", nt_errstr(status));
8966                 return false;
8967         }
8968
8969         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8970         if (!NT_STATUS_IS_OK(status)) {
8971                 d_printf("cli_list failed: %s\n", nt_errstr(status));
8972                 return false;
8973         }
8974
8975         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8976         if (mangled_path == NULL) {
8977                 return false;
8978         }
8979
8980         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8981         if (!NT_STATUS_IS_OK(status)) {
8982                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8983                 TALLOC_FREE(mangled_path);
8984                 return false;
8985         }
8986         TALLOC_FREE(mangled_path);
8987         cli_close(cli, fnum);
8988
8989         cli_setatr(cli_posix, illegal_fname, 0, 0);
8990         cli_posix_unlink(cli_posix, illegal_fname);
8991
8992         /*
8993          * Create a file with a long name and check that we got *no* short name.
8994          */
8995
8996         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8997                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8998                               0, 0, &fnum, NULL);
8999         if (!NT_STATUS_IS_OK(status)) {
9000                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
9001                 return false;
9002         }
9003         cli_close(cli, fnum);
9004
9005         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
9006         if (!NT_STATUS_IS_OK(status)) {
9007                 d_printf("cli_list failed\n");
9008                 return false;
9009         }
9010
9011         cli_unlink(cli, fname, 0);
9012         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
9013
9014         if (!torture_close_connection(cli_posix)) {
9015                 return false;
9016         }
9017
9018         if (!torture_close_connection(cli)) {
9019                 return false;
9020         }
9021
9022         return true;
9023 }
9024
9025 static size_t null_source(uint8_t *buf, size_t n, void *priv)
9026 {
9027         size_t *to_pull = (size_t *)priv;
9028         size_t thistime = *to_pull;
9029
9030         thistime = MIN(thistime, n);
9031         if (thistime == 0) {
9032                 return 0;
9033         }
9034
9035         memset(buf, 0, thistime);
9036         *to_pull -= thistime;
9037         return thistime;
9038 }
9039
9040 static bool run_windows_write(int dummy)
9041 {
9042         struct cli_state *cli1;
9043         uint16_t fnum;
9044         int i;
9045         bool ret = false;
9046         const char *fname = "\\writetest.txt";
9047         struct timeval start_time;
9048         double seconds;
9049         double kbytes;
9050         NTSTATUS status;
9051
9052         printf("starting windows_write test\n");
9053         if (!torture_open_connection(&cli1, 0)) {
9054                 return False;
9055         }
9056
9057         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9058         if (!NT_STATUS_IS_OK(status)) {
9059                 printf("open failed (%s)\n", nt_errstr(status));
9060                 return False;
9061         }
9062
9063         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9064
9065         start_time = timeval_current();
9066
9067         for (i=0; i<torture_numops; i++) {
9068                 uint8_t c = 0;
9069                 off_t start = i * torture_blocksize;
9070                 size_t to_pull = torture_blocksize - 1;
9071
9072                 status = cli_writeall(cli1, fnum, 0, &c,
9073                                       start + torture_blocksize - 1, 1, NULL);
9074                 if (!NT_STATUS_IS_OK(status)) {
9075                         printf("cli_write failed: %s\n", nt_errstr(status));
9076                         goto fail;
9077                 }
9078
9079                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
9080                                   null_source, &to_pull);
9081                 if (!NT_STATUS_IS_OK(status)) {
9082                         printf("cli_push returned: %s\n", nt_errstr(status));
9083                         goto fail;
9084                 }
9085         }
9086
9087         seconds = timeval_elapsed(&start_time);
9088         kbytes = (double)torture_blocksize * torture_numops;
9089         kbytes /= 1024;
9090
9091         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
9092                (double)seconds, (int)(kbytes/seconds));
9093
9094         ret = true;
9095  fail:
9096         cli_close(cli1, fnum);
9097         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9098         torture_close_connection(cli1);
9099         return ret;
9100 }
9101
9102 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
9103 {
9104         size_t max_pdu = 0x1FFFF;
9105
9106         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
9107                 max_pdu = 0xFFFFFF;
9108         }
9109
9110         if (smb1cli_conn_signing_is_active(cli->conn)) {
9111                 max_pdu = 0x1FFFF;
9112         }
9113
9114         if (smb1cli_conn_encryption_on(cli->conn)) {
9115                 max_pdu = CLI_BUFFER_SIZE;
9116         }
9117
9118         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
9119                 len_requested &= 0xFFFF;
9120         }
9121
9122         return MIN(len_requested,
9123                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
9124 }
9125
9126 static bool check_read_call(struct cli_state *cli,
9127                             uint16_t fnum,
9128                             uint8_t *buf,
9129                             size_t len_requested)
9130 {
9131         NTSTATUS status;
9132         struct tevent_req *subreq = NULL;
9133         ssize_t len_read = 0;
9134         size_t len_expected = 0;
9135         struct tevent_context *ev = NULL;
9136
9137         ev = samba_tevent_context_init(talloc_tos());
9138         if (ev == NULL) {
9139                 return false;
9140         }
9141
9142         subreq = cli_read_andx_send(talloc_tos(),
9143                                     ev,
9144                                     cli,
9145                                     fnum,
9146                                     0,
9147                                     len_requested);
9148
9149         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
9150                 return false;
9151         }
9152
9153         status = cli_read_andx_recv(subreq, &len_read, &buf);
9154         if (!NT_STATUS_IS_OK(status)) {
9155                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
9156                 return false;
9157         }
9158
9159         TALLOC_FREE(subreq);
9160         TALLOC_FREE(ev);
9161
9162         len_expected = calc_expected_return(cli, len_requested);
9163
9164         if (len_expected > 0x10000 && len_read == 0x10000) {
9165                 /* Windows servers only return a max of 0x10000,
9166                    doesn't matter if you set CAP_LARGE_READX in
9167                    the client sessionsetupX call or not. */
9168                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
9169                         (unsigned int)len_requested);
9170         } else if (len_read != len_expected) {
9171                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
9172                         (unsigned int)len_requested,
9173                         (unsigned int)len_read,
9174                         (unsigned int)len_expected);
9175                 return false;
9176         } else {
9177                 d_printf("Correct read reply.\n");
9178         }
9179
9180         return true;
9181 }
9182
9183 /* Test large readX variants. */
9184 static bool large_readx_tests(struct cli_state *cli,
9185                                 uint16_t fnum,
9186                                 uint8_t *buf)
9187 {
9188         /* A read of 0xFFFF0001 should *always* return 1 byte. */
9189         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
9190                 return false;
9191         }
9192         /* A read of 0x10000 should return 0x10000 bytes. */
9193         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
9194                 return false;
9195         }
9196         /* A read of 0x10000 should return 0x10001 bytes. */
9197         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
9198                 return false;
9199         }
9200         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
9201            the requested number of bytes. */
9202         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
9203                 return false;
9204         }
9205         /* A read of 1MB should return 1MB bytes (on Samba). */
9206         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
9207                 return false;
9208         }
9209
9210         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
9211                 return false;
9212         }
9213         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
9214                 return false;
9215         }
9216         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
9217                 return false;
9218         }
9219         return true;
9220 }
9221
9222 static bool run_large_readx(int dummy)
9223 {
9224         uint8_t *buf = NULL;
9225         struct cli_state *cli1 = NULL;
9226         struct cli_state *cli2 = NULL;
9227         bool correct = false;
9228         const char *fname = "\\large_readx.dat";
9229         NTSTATUS status;
9230         uint16_t fnum1 = UINT16_MAX;
9231         uint32_t normal_caps = 0;
9232         size_t file_size = 20*1024*1024;
9233         TALLOC_CTX *frame = talloc_stackframe();
9234         size_t i;
9235         struct {
9236                 const char *name;
9237                 enum smb_signing_setting signing_setting;
9238                 enum protocol_types protocol;
9239         } runs[] = {
9240                 {
9241                         .name = "NT1",
9242                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
9243                         .protocol = PROTOCOL_NT1,
9244                 },{
9245                         .name = "NT1 - SIGNING_REQUIRED",
9246                         .signing_setting = SMB_SIGNING_REQUIRED,
9247                         .protocol = PROTOCOL_NT1,
9248                 },
9249         };
9250
9251         printf("starting large_readx test\n");
9252
9253         if (!torture_open_connection(&cli1, 0)) {
9254                 goto out;
9255         }
9256
9257         normal_caps = smb1cli_conn_capabilities(cli1->conn);
9258
9259         if (!(normal_caps & CAP_LARGE_READX)) {
9260                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9261                         (unsigned int)normal_caps);
9262                 goto out;
9263         }
9264
9265         /* Create a file of size 4MB. */
9266         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
9267                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9268                         0, 0, &fnum1, NULL);
9269
9270         if (!NT_STATUS_IS_OK(status)) {
9271                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
9272                 goto out;
9273         }
9274
9275         /* Write file_size bytes. */
9276         buf = talloc_zero_array(frame, uint8_t, file_size);
9277         if (buf == NULL) {
9278                 goto out;
9279         }
9280
9281         status = cli_writeall(cli1,
9282                               fnum1,
9283                               0,
9284                               buf,
9285                               0,
9286                               file_size,
9287                               NULL);
9288         if (!NT_STATUS_IS_OK(status)) {
9289                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9290                 goto out;
9291         }
9292
9293         status = cli_close(cli1, fnum1);
9294         if (!NT_STATUS_IS_OK(status)) {
9295                 d_printf("cli_close failed: %s\n", nt_errstr(status));
9296                 goto out;
9297         }
9298
9299         fnum1 = UINT16_MAX;
9300
9301         for (i=0; i < ARRAY_SIZE(runs); i++) {
9302                 enum smb_signing_setting saved_signing_setting = signing_state;
9303                 uint16_t fnum2 = -1;
9304
9305                 if (do_encrypt &&
9306                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
9307                 {
9308                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
9309                         continue;
9310                 }
9311
9312                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
9313
9314                 signing_state = runs[i].signing_setting;
9315                 cli2 = open_nbt_connection();
9316                 signing_state = saved_signing_setting;
9317                 if (cli2 == NULL) {
9318                         goto out;
9319                 }
9320
9321                 status = smbXcli_negprot(cli2->conn,
9322                                          cli2->timeout,
9323                                          runs[i].protocol,
9324                                          runs[i].protocol);
9325                 if (!NT_STATUS_IS_OK(status)) {
9326                         goto out;
9327                 }
9328
9329                 status = cli_session_setup_creds(cli2, torture_creds);
9330                 if (!NT_STATUS_IS_OK(status)) {
9331                         goto out;
9332                 }
9333
9334                 status = cli_tree_connect(cli2,
9335                                         share,
9336                                         "?????",
9337                                         password);
9338                 if (!NT_STATUS_IS_OK(status)) {
9339                         goto out;
9340                 }
9341
9342                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
9343
9344                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
9345
9346                 if (!(normal_caps & CAP_LARGE_READX)) {
9347                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9348                                 (unsigned int)normal_caps);
9349                         goto out;
9350                 }
9351
9352                 if (do_encrypt) {
9353                         if (force_cli_encryption(cli2, share) == false) {
9354                                 goto out;
9355                         }
9356                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
9357                         uint16_t major, minor;
9358                         uint32_t caplow, caphigh;
9359
9360                         status = cli_unix_extensions_version(cli2,
9361                                                              &major, &minor,
9362                                                              &caplow, &caphigh);
9363                         if (!NT_STATUS_IS_OK(status)) {
9364                                 goto out;
9365                         }
9366                 }
9367
9368                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
9369                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
9370                                 0, 0, &fnum2, NULL);
9371                 if (!NT_STATUS_IS_OK(status)) {
9372                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
9373                         goto out;
9374                 }
9375
9376                 /* All reads must return less than file_size bytes. */
9377                 if (!large_readx_tests(cli2, fnum2, buf)) {
9378                         goto out;
9379                 }
9380
9381                 status = cli_close(cli2, fnum2);
9382                 if (!NT_STATUS_IS_OK(status)) {
9383                         d_printf("cli_close failed: %s\n", nt_errstr(status));
9384                         goto out;
9385                 }
9386                 fnum2 = -1;
9387
9388                 if (!torture_close_connection(cli2)) {
9389                         goto out;
9390                 }
9391                 cli2 = NULL;
9392         }
9393
9394         correct = true;
9395         printf("Success on large_readx test\n");
9396
9397   out:
9398
9399         if (cli2) {
9400                 if (!torture_close_connection(cli2)) {
9401                         correct = false;
9402                 }
9403         }
9404
9405         if (cli1) {
9406                 if (fnum1 != UINT16_MAX) {
9407                         status = cli_close(cli1, fnum1);
9408                         if (!NT_STATUS_IS_OK(status)) {
9409                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
9410                         }
9411                         fnum1 = UINT16_MAX;
9412                 }
9413
9414                 status = cli_unlink(cli1, fname,
9415                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9416                 if (!NT_STATUS_IS_OK(status)) {
9417                         printf("unlink failed (%s)\n", nt_errstr(status));
9418                 }
9419
9420                 if (!torture_close_connection(cli1)) {
9421                         correct = false;
9422                 }
9423         }
9424
9425         TALLOC_FREE(frame);
9426
9427         printf("finished large_readx test\n");
9428         return correct;
9429 }
9430
9431 static bool run_cli_echo(int dummy)
9432 {
9433         struct cli_state *cli;
9434         NTSTATUS status;
9435
9436         printf("starting cli_echo test\n");
9437         if (!torture_open_connection(&cli, 0)) {
9438                 return false;
9439         }
9440         smbXcli_conn_set_sockopt(cli->conn, sockops);
9441
9442         status = cli_echo(cli, 5, data_blob_const("hello", 5));
9443
9444         d_printf("cli_echo returned %s\n", nt_errstr(status));
9445
9446         torture_close_connection(cli);
9447         return NT_STATUS_IS_OK(status);
9448 }
9449
9450 static int splice_status(off_t written, void *priv)
9451 {
9452         return true;
9453 }
9454
9455 static bool run_cli_splice(int dummy)
9456 {
9457         uint8_t *buf = NULL;
9458         struct cli_state *cli1 = NULL;
9459         bool correct = false;
9460         const char *fname_src = "\\splice_src.dat";
9461         const char *fname_dst = "\\splice_dst.dat";
9462         NTSTATUS status;
9463         uint16_t fnum1 = UINT16_MAX;
9464         uint16_t fnum2 = UINT16_MAX;
9465         size_t file_size = 2*1024*1024;
9466         size_t splice_size = 1*1024*1024 + 713;
9467         MD5_CTX md5_ctx;
9468         uint8_t digest1[16], digest2[16];
9469         off_t written = 0;
9470         size_t nread = 0;
9471         TALLOC_CTX *frame = talloc_stackframe();
9472
9473         printf("starting cli_splice test\n");
9474
9475         if (!torture_open_connection(&cli1, 0)) {
9476                 goto out;
9477         }
9478
9479         cli_unlink(cli1, fname_src,
9480                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9481         cli_unlink(cli1, fname_dst,
9482                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9483
9484         /* Create a file */
9485         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
9486                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9487                         0, 0, &fnum1, NULL);
9488
9489         if (!NT_STATUS_IS_OK(status)) {
9490                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
9491                 goto out;
9492         }
9493
9494         /* Write file_size bytes - must be bigger than splice_size. */
9495         buf = talloc_zero_array(frame, uint8_t, file_size);
9496         if (buf == NULL) {
9497                 d_printf("talloc_fail\n");
9498                 goto out;
9499         }
9500
9501         /* Fill it with random numbers. */
9502         generate_random_buffer(buf, file_size);
9503
9504         /* MD5 the first 1MB + 713 bytes. */
9505         MD5Init(&md5_ctx);
9506         MD5Update(&md5_ctx, buf, splice_size);
9507         MD5Final(digest1, &md5_ctx);
9508
9509         status = cli_writeall(cli1,
9510                               fnum1,
9511                               0,
9512                               buf,
9513                               0,
9514                               file_size,
9515                               NULL);
9516         if (!NT_STATUS_IS_OK(status)) {
9517                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9518                 goto out;
9519         }
9520
9521         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
9522                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9523                         0, 0, &fnum2, NULL);
9524
9525         if (!NT_STATUS_IS_OK(status)) {
9526                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
9527                 goto out;
9528         }
9529
9530         /* Now splice 1MB + 713 bytes. */
9531         status = cli_splice(cli1,
9532                                 cli1,
9533                                 fnum1,
9534                                 fnum2,
9535                                 splice_size,
9536                                 0,
9537                                 0,
9538                                 &written,
9539                                 splice_status,
9540                                 NULL);
9541
9542         if (!NT_STATUS_IS_OK(status)) {
9543                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
9544                 goto out;
9545         }
9546
9547         /* Clear the old buffer. */
9548         memset(buf, '\0', file_size);
9549
9550         /* Read the new file. */
9551         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
9552         if (!NT_STATUS_IS_OK(status)) {
9553                 d_printf("cli_read failed: %s\n", nt_errstr(status));
9554                 goto out;
9555         }
9556         if (nread != splice_size) {
9557                 d_printf("bad read of 0x%x, should be 0x%x\n",
9558                         (unsigned int)nread,
9559                         (unsigned int)splice_size);
9560                 goto out;
9561         }
9562
9563         /* MD5 the first 1MB + 713 bytes. */
9564         MD5Init(&md5_ctx);
9565         MD5Update(&md5_ctx, buf, splice_size);
9566         MD5Final(digest2, &md5_ctx);
9567
9568         /* Must be the same. */
9569         if (memcmp(digest1, digest2, 16) != 0) {
9570                 d_printf("bad MD5 compare\n");
9571                 goto out;
9572         }
9573
9574         correct = true;
9575         printf("Success on cli_splice test\n");
9576
9577   out:
9578
9579         if (cli1) {
9580                 if (fnum1 != UINT16_MAX) {
9581                         cli_close(cli1, fnum1);
9582                 }
9583                 if (fnum2 != UINT16_MAX) {
9584                         cli_close(cli1, fnum2);
9585                 }
9586
9587                 cli_unlink(cli1, fname_src,
9588                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9589                 cli_unlink(cli1, fname_dst,
9590                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9591
9592                 if (!torture_close_connection(cli1)) {
9593                         correct = false;
9594                 }
9595         }
9596
9597         TALLOC_FREE(frame);
9598         return correct;
9599 }
9600
9601 static bool run_uid_regression_test(int dummy)
9602 {
9603         static struct cli_state *cli;
9604         int16_t old_vuid;
9605         int32_t old_cnum;
9606         bool correct = True;
9607         struct smbXcli_tcon *orig_tcon = NULL;
9608         NTSTATUS status;
9609
9610         printf("starting uid regression test\n");
9611
9612         if (!torture_open_connection(&cli, 0)) {
9613                 return False;
9614         }
9615
9616         smbXcli_conn_set_sockopt(cli->conn, sockops);
9617
9618         /* Ok - now save then logoff our current user. */
9619         old_vuid = cli_state_get_uid(cli);
9620
9621         status = cli_ulogoff(cli);
9622         if (!NT_STATUS_IS_OK(status)) {
9623                 d_printf("(%s) cli_ulogoff failed: %s\n",
9624                          __location__, nt_errstr(status));
9625                 correct = false;
9626                 goto out;
9627         }
9628
9629         cli_state_set_uid(cli, old_vuid);
9630
9631         /* Try an operation. */
9632         status = cli_mkdir(cli, "\\uid_reg_test");
9633         if (NT_STATUS_IS_OK(status)) {
9634                 d_printf("(%s) cli_mkdir succeeded\n",
9635                          __location__);
9636                 correct = false;
9637                 goto out;
9638         } else {
9639                 /* Should be bad uid. */
9640                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9641                                  NT_STATUS_USER_SESSION_DELETED)) {
9642                         correct = false;
9643                         goto out;
9644                 }
9645         }
9646
9647         old_cnum = cli_state_get_tid(cli);
9648         orig_tcon = cli_state_save_tcon(cli);
9649         if (orig_tcon == NULL) {
9650                 correct = false;
9651                 goto out;
9652         }
9653
9654         /* Now try a SMBtdis with the invald vuid set to zero. */
9655         cli_state_set_uid(cli, 0);
9656
9657         /* This should succeed. */
9658         status = cli_tdis(cli);
9659
9660         if (NT_STATUS_IS_OK(status)) {
9661                 d_printf("First tdis with invalid vuid should succeed.\n");
9662         } else {
9663                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9664                 correct = false;
9665                 cli_state_restore_tcon(cli, orig_tcon);
9666                 goto out;
9667         }
9668
9669         cli_state_restore_tcon(cli, orig_tcon);
9670         cli_state_set_uid(cli, old_vuid);
9671         cli_state_set_tid(cli, old_cnum);
9672
9673         /* This should fail. */
9674         status = cli_tdis(cli);
9675         if (NT_STATUS_IS_OK(status)) {
9676                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9677                 correct = false;
9678                 goto out;
9679         } else {
9680                 /* Should be bad tid. */
9681                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9682                                 NT_STATUS_NETWORK_NAME_DELETED)) {
9683                         correct = false;
9684                         goto out;
9685                 }
9686         }
9687
9688         cli_rmdir(cli, "\\uid_reg_test");
9689
9690   out:
9691
9692         cli_shutdown(cli);
9693         return correct;
9694 }
9695
9696
9697 static const char *illegal_chars = "*\\/?<>|\":";
9698 static char force_shortname_chars[] = " +,.[];=\177";
9699
9700 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9701                              const char *mask, void *state)
9702 {
9703         struct cli_state *pcli = (struct cli_state *)state;
9704         fstring fname;
9705         NTSTATUS status = NT_STATUS_OK;
9706
9707         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9708
9709         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9710                 return NT_STATUS_OK;
9711
9712         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9713                 status = cli_rmdir(pcli, fname);
9714                 if (!NT_STATUS_IS_OK(status)) {
9715                         printf("del_fn: failed to rmdir %s\n,", fname );
9716                 }
9717         } else {
9718                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9719                 if (!NT_STATUS_IS_OK(status)) {
9720                         printf("del_fn: failed to unlink %s\n,", fname );
9721                 }
9722         }
9723         return status;
9724 }
9725
9726 struct sn_state {
9727         int matched;
9728         int i;
9729         bool val;
9730 };
9731
9732 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9733                               const char *name, void *state)
9734 {
9735         struct sn_state *s = (struct sn_state  *)state;
9736         int i = s->i;
9737
9738 #if 0
9739         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9740                 i, finfo->name, finfo->short_name);
9741 #endif
9742
9743         if (strchr(force_shortname_chars, i)) {
9744                 if (!finfo->short_name) {
9745                         /* Shortname not created when it should be. */
9746                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9747                                 __location__, finfo->name, i);
9748                         s->val = true;
9749                 }
9750         } else if (finfo->short_name){
9751                 /* Shortname created when it should not be. */
9752                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9753                         __location__, finfo->short_name, finfo->name);
9754                 s->val = true;
9755         }
9756         s->matched += 1;
9757         return NT_STATUS_OK;
9758 }
9759
9760 static bool run_shortname_test(int dummy)
9761 {
9762         static struct cli_state *cli;
9763         bool correct = True;
9764         int i;
9765         struct sn_state s;
9766         char fname[40];
9767         NTSTATUS status;
9768
9769         printf("starting shortname test\n");
9770
9771         if (!torture_open_connection(&cli, 0)) {
9772                 return False;
9773         }
9774
9775         smbXcli_conn_set_sockopt(cli->conn, sockops);
9776
9777         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9778         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9779         cli_rmdir(cli, "\\shortname");
9780
9781         status = cli_mkdir(cli, "\\shortname");
9782         if (!NT_STATUS_IS_OK(status)) {
9783                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9784                         __location__, nt_errstr(status));
9785                 correct = false;
9786                 goto out;
9787         }
9788
9789         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9790                 correct = false;
9791                 goto out;
9792         }
9793         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9794                 correct = false;
9795                 goto out;
9796         }
9797
9798         s.val = false;
9799
9800         for (i = 32; i < 128; i++) {
9801                 uint16_t fnum = (uint16_t)-1;
9802
9803                 s.i = i;
9804
9805                 if (strchr(illegal_chars, i)) {
9806                         continue;
9807                 }
9808                 fname[15] = i;
9809
9810                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9811                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
9812                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9813                 if (!NT_STATUS_IS_OK(status)) {
9814                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
9815                                 __location__, fname, nt_errstr(status));
9816                         correct = false;
9817                         goto out;
9818                 }
9819                 cli_close(cli, fnum);
9820
9821                 s.matched = 0;
9822                 status = cli_list(cli, "\\shortname\\test*.*", 0,
9823                                   shortname_list_fn, &s);
9824                 if (s.matched != 1) {
9825                         d_printf("(%s) failed to list %s: %s\n",
9826                                 __location__, fname, nt_errstr(status));
9827                         correct = false;
9828                         goto out;
9829                 }
9830
9831                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9832                 if (!NT_STATUS_IS_OK(status)) {
9833                         d_printf("(%s) failed to delete %s: %s\n",
9834                                 __location__, fname, nt_errstr(status));
9835                         correct = false;
9836                         goto out;
9837                 }
9838
9839                 if (s.val) {
9840                         correct = false;
9841                         goto out;
9842                 }
9843         }
9844
9845   out:
9846
9847         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9848         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9849         cli_rmdir(cli, "\\shortname");
9850         torture_close_connection(cli);
9851         return correct;
9852 }
9853
9854 static void pagedsearch_cb(struct tevent_req *req)
9855 {
9856         TLDAPRC rc;
9857         struct tldap_message *msg;
9858         char *dn;
9859
9860         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9861         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9862                 d_printf("tldap_search_paged_recv failed: %s\n",
9863                          tldap_rc2string(rc));
9864                 return;
9865         }
9866         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9867                 TALLOC_FREE(msg);
9868                 return;
9869         }
9870         if (!tldap_entry_dn(msg, &dn)) {
9871                 d_printf("tldap_entry_dn failed\n");
9872                 return;
9873         }
9874         d_printf("%s\n", dn);
9875         TALLOC_FREE(msg);
9876 }
9877
9878 static bool run_tldap(int dummy)
9879 {
9880         struct tldap_context *ld;
9881         int fd;
9882         TLDAPRC rc;
9883         NTSTATUS status;
9884         struct sockaddr_storage addr;
9885         struct tevent_context *ev;
9886         struct tevent_req *req;
9887         char *basedn;
9888         const char *filter;
9889
9890         if (!resolve_name(host, &addr, 0, false)) {
9891                 d_printf("could not find host %s\n", host);
9892                 return false;
9893         }
9894         status = open_socket_out(&addr, 389, 9999, &fd);
9895         if (!NT_STATUS_IS_OK(status)) {
9896                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9897                 return false;
9898         }
9899
9900         ld = tldap_context_create(talloc_tos(), fd);
9901         if (ld == NULL) {
9902                 close(fd);
9903                 d_printf("tldap_context_create failed\n");
9904                 return false;
9905         }
9906
9907         rc = tldap_fetch_rootdse(ld);
9908         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9909                 d_printf("tldap_fetch_rootdse failed: %s\n",
9910                          tldap_errstr(talloc_tos(), ld, rc));
9911                 return false;
9912         }
9913
9914         basedn = tldap_talloc_single_attribute(
9915                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9916         if (basedn == NULL) {
9917                 d_printf("no defaultNamingContext\n");
9918                 return false;
9919         }
9920         d_printf("defaultNamingContext: %s\n", basedn);
9921
9922         ev = samba_tevent_context_init(talloc_tos());
9923         if (ev == NULL) {
9924                 d_printf("tevent_context_init failed\n");
9925                 return false;
9926         }
9927
9928         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9929                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
9930                                       NULL, 0, 0,
9931                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
9932         if (req == NULL) {
9933                 d_printf("tldap_search_paged_send failed\n");
9934                 return false;
9935         }
9936         tevent_req_set_callback(req, pagedsearch_cb, NULL);
9937
9938         tevent_req_poll(req, ev);
9939
9940         TALLOC_FREE(req);
9941
9942         /* test search filters against rootDSE */
9943         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9944                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9945
9946         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9947                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9948                           talloc_tos(), NULL);
9949         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9950                 d_printf("tldap_search with complex filter failed: %s\n",
9951                          tldap_errstr(talloc_tos(), ld, rc));
9952                 return false;
9953         }
9954
9955         TALLOC_FREE(ld);
9956         return true;
9957 }
9958
9959 /* Torture test to ensure no regression of :
9960 https://bugzilla.samba.org/show_bug.cgi?id=7084
9961 */
9962
9963 static bool run_dir_createtime(int dummy)
9964 {
9965         struct cli_state *cli;
9966         const char *dname = "\\testdir_createtime";
9967         const char *fname = "\\testdir_createtime\\testfile";
9968         NTSTATUS status;
9969         struct timespec create_time;
9970         struct timespec create_time1;
9971         uint16_t fnum;
9972         bool ret = false;
9973
9974         if (!torture_open_connection(&cli, 0)) {
9975                 return false;
9976         }
9977
9978         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9979         cli_rmdir(cli, dname);
9980
9981         status = cli_mkdir(cli, dname);
9982         if (!NT_STATUS_IS_OK(status)) {
9983                 printf("mkdir failed: %s\n", nt_errstr(status));
9984                 goto out;
9985         }
9986
9987         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9988                                 NULL, NULL, NULL);
9989         if (!NT_STATUS_IS_OK(status)) {
9990                 printf("cli_qpathinfo2 returned %s\n",
9991                        nt_errstr(status));
9992                 goto out;
9993         }
9994
9995         /* Sleep 3 seconds, then create a file. */
9996         sleep(3);
9997
9998         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
9999                          DENY_NONE, &fnum);
10000         if (!NT_STATUS_IS_OK(status)) {
10001                 printf("cli_openx failed: %s\n", nt_errstr(status));
10002                 goto out;
10003         }
10004
10005         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
10006                                 NULL, NULL, NULL);
10007         if (!NT_STATUS_IS_OK(status)) {
10008                 printf("cli_qpathinfo2 (2) returned %s\n",
10009                        nt_errstr(status));
10010                 goto out;
10011         }
10012
10013         if (timespec_compare(&create_time1, &create_time)) {
10014                 printf("run_dir_createtime: create time was updated (error)\n");
10015         } else {
10016                 printf("run_dir_createtime: create time was not updated (correct)\n");
10017                 ret = true;
10018         }
10019
10020   out:
10021
10022         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10023         cli_rmdir(cli, dname);
10024         if (!torture_close_connection(cli)) {
10025                 ret = false;
10026         }
10027         return ret;
10028 }
10029
10030
10031 static bool run_streamerror(int dummy)
10032 {
10033         struct cli_state *cli;
10034         const char *dname = "\\testdir_streamerror";
10035         const char *streamname =
10036                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
10037         NTSTATUS status;
10038         time_t change_time, access_time, write_time;
10039         off_t size;
10040         uint16_t mode, fnum;
10041         bool ret = true;
10042
10043         if (!torture_open_connection(&cli, 0)) {
10044                 return false;
10045         }
10046
10047         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10048         cli_rmdir(cli, dname);
10049
10050         status = cli_mkdir(cli, dname);
10051         if (!NT_STATUS_IS_OK(status)) {
10052                 printf("mkdir failed: %s\n", nt_errstr(status));
10053                 return false;
10054         }
10055
10056         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
10057                                 &write_time, &size, &mode);
10058         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
10059                 printf("pathinfo returned %s, expected "
10060                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
10061                        nt_errstr(status));
10062                 ret = false;
10063         }
10064
10065         status = cli_ntcreate(cli, streamname, 0x16,
10066                               FILE_READ_DATA|FILE_READ_EA|
10067                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
10068                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
10069                               FILE_OPEN, 0, 0, &fnum, NULL);
10070
10071         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
10072                 printf("ntcreate returned %s, expected "
10073                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
10074                        nt_errstr(status));
10075                 ret = false;
10076         }
10077
10078
10079         cli_rmdir(cli, dname);
10080         return ret;
10081 }
10082
10083 struct pidtest_state {
10084         bool success;
10085         uint16_t vwv[1];
10086         DATA_BLOB data;
10087 };
10088
10089 static void pid_echo_done(struct tevent_req *subreq);
10090
10091 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
10092                         struct tevent_context *ev,
10093                         struct cli_state *cli)
10094 {
10095         struct tevent_req *req, *subreq;
10096         struct pidtest_state *state;
10097
10098         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
10099         if (req == NULL) {
10100                 return NULL;
10101         }
10102
10103         SSVAL(state->vwv, 0, 1);
10104         state->data = data_blob_const("hello", 5);
10105
10106         subreq = smb1cli_req_send(state,
10107                                 ev,
10108                                 cli->conn,
10109                                 SMBecho,
10110                                 0, 0, /* *_flags */
10111                                 0, 0, /* *_flags2 */
10112                                 cli->timeout,
10113                                 0xDEADBEEF, /* pid */
10114                                 NULL, /* tcon */
10115                                 NULL, /* session */
10116                                 ARRAY_SIZE(state->vwv), state->vwv,
10117                                 state->data.length, state->data.data);
10118
10119         if (tevent_req_nomem(subreq, req)) {
10120                 return tevent_req_post(req, ev);
10121         }
10122         tevent_req_set_callback(subreq, pid_echo_done, req);
10123         return req;
10124 }
10125
10126 static void pid_echo_done(struct tevent_req *subreq)
10127 {
10128         struct tevent_req *req = tevent_req_callback_data(
10129                 subreq, struct tevent_req);
10130         struct pidtest_state *state = tevent_req_data(
10131                 req, struct pidtest_state);
10132         NTSTATUS status;
10133         uint32_t num_bytes;
10134         uint8_t *bytes = NULL;
10135         struct iovec *recv_iov = NULL;
10136         uint8_t *phdr = NULL;
10137         uint16_t pidlow = 0;
10138         uint16_t pidhigh = 0;
10139         struct smb1cli_req_expected_response expected[] = {
10140         {
10141                 .status = NT_STATUS_OK,
10142                 .wct    = 1,
10143         },
10144         };
10145
10146         status = smb1cli_req_recv(subreq, state,
10147                                 &recv_iov,
10148                                 &phdr,
10149                                 NULL, /* pwct */
10150                                 NULL, /* pvwv */
10151                                 NULL, /* pvwv_offset */
10152                                 &num_bytes,
10153                                 &bytes,
10154                                 NULL, /* pbytes_offset */
10155                                 NULL, /* pinbuf */
10156                                 expected, ARRAY_SIZE(expected));
10157
10158         TALLOC_FREE(subreq);
10159
10160         if (!NT_STATUS_IS_OK(status)) {
10161                 tevent_req_nterror(req, status);
10162                 return;
10163         }
10164
10165         if (num_bytes != state->data.length) {
10166                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10167                 return;
10168         }
10169
10170         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
10171                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10172                 return;
10173         }
10174
10175         /* Check pid low/high == DEADBEEF */
10176         pidlow = SVAL(phdr, HDR_PID);
10177         if (pidlow != 0xBEEF){
10178                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
10179                         (unsigned int)pidlow);
10180                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10181                 return;
10182         }
10183         pidhigh = SVAL(phdr, HDR_PIDHIGH);
10184         if (pidhigh != 0xDEAD){
10185                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
10186                         (unsigned int)pidhigh);
10187                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10188                 return;
10189         }
10190
10191         tevent_req_done(req);
10192 }
10193
10194 static NTSTATUS pid_echo_recv(struct tevent_req *req)
10195 {
10196         return tevent_req_simple_recv_ntstatus(req);
10197 }
10198
10199 static bool run_pidhigh(int dummy)
10200 {
10201         bool success = false;
10202         struct cli_state *cli = NULL;
10203         NTSTATUS status;
10204         struct tevent_context *ev = NULL;
10205         struct tevent_req *req = NULL;
10206         TALLOC_CTX *frame = talloc_stackframe();
10207
10208         printf("starting pid high test\n");
10209         if (!torture_open_connection(&cli, 0)) {
10210                 return false;
10211         }
10212         smbXcli_conn_set_sockopt(cli->conn, sockops);
10213
10214         ev = samba_tevent_context_init(frame);
10215         if (ev == NULL) {
10216                 goto fail;
10217         }
10218
10219         req = pid_echo_send(frame, ev, cli);
10220         if (req == NULL) {
10221                 goto fail;
10222         }
10223
10224         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
10225                 goto fail;
10226         }
10227
10228         status = pid_echo_recv(req);
10229         if (NT_STATUS_IS_OK(status)) {
10230                 printf("pid high test ok\n");
10231                 success = true;
10232         }
10233
10234  fail:
10235
10236         TALLOC_FREE(frame);
10237         torture_close_connection(cli);
10238         return success;
10239 }
10240
10241 /*
10242   Test Windows open on a bad POSIX symlink.
10243  */
10244 static bool run_symlink_open_test(int dummy)
10245 {
10246         static struct cli_state *cli;
10247         const char *fname = "non_existant_file";
10248         const char *sname = "dangling_symlink";
10249         uint16_t fnum = (uint16_t)-1;
10250         bool correct = false;
10251         NTSTATUS status;
10252         TALLOC_CTX *frame = NULL;
10253
10254         frame = talloc_stackframe();
10255
10256         printf("Starting Windows bad symlink open test\n");
10257
10258         if (!torture_open_connection(&cli, 0)) {
10259                 TALLOC_FREE(frame);
10260                 return false;
10261         }
10262
10263         smbXcli_conn_set_sockopt(cli->conn, sockops);
10264
10265         status = torture_setup_unix_extensions(cli);
10266         if (!NT_STATUS_IS_OK(status)) {
10267                 TALLOC_FREE(frame);
10268                 return false;
10269         }
10270
10271         /* Ensure nothing exists. */
10272         cli_setatr(cli, fname, 0, 0);
10273         cli_posix_unlink(cli, fname);
10274         cli_setatr(cli, sname, 0, 0);
10275         cli_posix_unlink(cli, sname);
10276
10277         /* Create a symlink pointing nowhere. */
10278         status = cli_posix_symlink(cli, fname, sname);
10279         if (!NT_STATUS_IS_OK(status)) {
10280                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
10281                         sname,
10282                         fname,
10283                         nt_errstr(status));
10284                 goto out;
10285         }
10286
10287         /* Now ensure that a Windows open doesn't hang. */
10288         status = cli_ntcreate(cli,
10289                         sname,
10290                         0,
10291                         FILE_READ_DATA|FILE_WRITE_DATA,
10292                         0,
10293                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10294                         FILE_OPEN_IF,
10295                         0x0,
10296                         0x0,
10297                         &fnum,
10298                         NULL);
10299
10300         /*
10301          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
10302          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
10303          * we use O_NOFOLLOW on the server or not.
10304          */
10305         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
10306             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
10307         {
10308                 correct = true;
10309         } else {
10310                 printf("cli_ntcreate of %s returned %s - should return"
10311                                 " either (%s) or (%s)\n",
10312                         sname,
10313                         nt_errstr(status),
10314                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
10315                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
10316                 goto out;
10317         }
10318
10319         correct = true;
10320
10321   out:
10322
10323         if (fnum != (uint16_t)-1) {
10324                 cli_close(cli, fnum);
10325                 fnum = (uint16_t)-1;
10326         }
10327
10328         cli_setatr(cli, sname, 0, 0);
10329         cli_posix_unlink(cli, sname);
10330         cli_setatr(cli, fname, 0, 0);
10331         cli_posix_unlink(cli, fname);
10332
10333         if (!torture_close_connection(cli)) {
10334                 correct = false;
10335         }
10336
10337         TALLOC_FREE(frame);
10338         return correct;
10339 }
10340
10341 /*
10342  * Only testing minimal time strings, as the others
10343  * need (locale-dependent) guessing at what strftime does and
10344  * even may differ in builds.
10345  */
10346 static bool timesubst_test(void)
10347 {
10348         TALLOC_CTX *ctx = NULL;
10349         /* Sa 23. Dez 04:33:20 CET 2017 */
10350         const struct timeval tv = { 1514000000, 123 };
10351         const char* expect_minimal = "20171223_033320";
10352         const char* expect_minus   = "20171223_033320_000123";
10353         char *s;
10354         char *env_tz, *orig_tz = NULL;
10355         bool result = true;
10356
10357         ctx = talloc_new(NULL);
10358
10359         env_tz = getenv("TZ");
10360         if(env_tz) {
10361                 orig_tz = talloc_strdup(ctx, env_tz);
10362         }
10363         setenv("TZ", "UTC", 1);
10364
10365         s = minimal_timeval_string(ctx, &tv, false);
10366
10367         if(!s || strcmp(s, expect_minimal)) {
10368                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
10369                        "[%s]\n", s ? s : "<nil>", expect_minimal);
10370                 result = false;
10371         }
10372         TALLOC_FREE(s);
10373         s = minimal_timeval_string(ctx, &tv, true);
10374         if(!s || strcmp(s, expect_minus)) {
10375                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
10376                        "[%s]\n", s ? s : "<nil>", expect_minus);
10377                 result = false;
10378         }
10379         TALLOC_FREE(s);
10380
10381         if(orig_tz) {
10382                 setenv("TZ", orig_tz, 1);
10383         }
10384
10385         TALLOC_FREE(ctx);
10386         return result;
10387 }
10388
10389 static bool run_local_substitute(int dummy)
10390 {
10391         bool ok = true;
10392
10393         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
10394         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
10395         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
10396         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
10397         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
10398         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
10399         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
10400         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
10401         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
10402         /* Substitution depends on current time, so better test the underlying
10403            formatting function. At least covers %t. */
10404         ok &= timesubst_test();
10405
10406         /* Different captialization rules in sub_basic... */
10407
10408         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
10409                        "blaDOM") == 0);
10410
10411         return ok;
10412 }
10413
10414 static bool run_local_base64(int dummy)
10415 {
10416         int i;
10417         bool ret = true;
10418
10419         for (i=1; i<2000; i++) {
10420                 DATA_BLOB blob1, blob2;
10421                 char *b64;
10422
10423                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
10424                 blob1.length = i;
10425                 generate_random_buffer(blob1.data, blob1.length);
10426
10427                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
10428                 if (b64 == NULL) {
10429                         d_fprintf(stderr, "base64_encode_data_blob failed "
10430                                   "for %d bytes\n", i);
10431                         ret = false;
10432                 }
10433                 blob2 = base64_decode_data_blob(b64);
10434                 TALLOC_FREE(b64);
10435
10436                 if (data_blob_cmp(&blob1, &blob2)) {
10437                         d_fprintf(stderr, "data_blob_cmp failed for %d "
10438                                   "bytes\n", i);
10439                         ret = false;
10440                 }
10441                 TALLOC_FREE(blob1.data);
10442                 data_blob_free(&blob2);
10443         }
10444         return ret;
10445 }
10446
10447 static void parse_fn(const struct gencache_timeout *t,
10448                      DATA_BLOB blob,
10449                      void *private_data)
10450 {
10451         return;
10452 }
10453
10454 static bool run_local_gencache(int dummy)
10455 {
10456         char *val;
10457         time_t tm;
10458         DATA_BLOB blob;
10459         char v;
10460         struct memcache *mem;
10461         int i;
10462
10463         mem = memcache_init(NULL, 0);
10464         if (mem == NULL) {
10465                 d_printf("%s: memcache_init failed\n", __location__);
10466                 return false;
10467         }
10468         memcache_set_global(mem);
10469
10470         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
10471                 d_printf("%s: gencache_set() failed\n", __location__);
10472                 return False;
10473         }
10474
10475         if (!gencache_get("foo", NULL, NULL, NULL)) {
10476                 d_printf("%s: gencache_get() failed\n", __location__);
10477                 return False;
10478         }
10479
10480         for (i=0; i<1000000; i++) {
10481                 gencache_parse("foo", parse_fn, NULL);
10482         }
10483
10484         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10485                 d_printf("%s: gencache_get() failed\n", __location__);
10486                 return False;
10487         }
10488         TALLOC_FREE(val);
10489
10490         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10491                 d_printf("%s: gencache_get() failed\n", __location__);
10492                 return False;
10493         }
10494
10495         if (strcmp(val, "bar") != 0) {
10496                 d_printf("%s: gencache_get() returned %s, expected %s\n",
10497                          __location__, val, "bar");
10498                 TALLOC_FREE(val);
10499                 return False;
10500         }
10501
10502         TALLOC_FREE(val);
10503
10504         if (!gencache_del("foo")) {
10505                 d_printf("%s: gencache_del() failed\n", __location__);
10506                 return False;
10507         }
10508         if (gencache_del("foo")) {
10509                 d_printf("%s: second gencache_del() succeeded\n",
10510                          __location__);
10511                 return False;
10512         }
10513
10514         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
10515                 d_printf("%s: gencache_get() on deleted entry "
10516                          "succeeded\n", __location__);
10517                 return False;
10518         }
10519
10520         blob = data_blob_string_const_null("bar");
10521         tm = time(NULL) + 60;
10522
10523         if (!gencache_set_data_blob("foo", blob, tm)) {
10524                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
10525                 return False;
10526         }
10527
10528         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10529                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
10530                 return False;
10531         }
10532
10533         if (strcmp((const char *)blob.data, "bar") != 0) {
10534                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
10535                          __location__, (const char *)blob.data, "bar");
10536                 data_blob_free(&blob);
10537                 return False;
10538         }
10539
10540         data_blob_free(&blob);
10541
10542         if (!gencache_del("foo")) {
10543                 d_printf("%s: gencache_del() failed\n", __location__);
10544                 return False;
10545         }
10546         if (gencache_del("foo")) {
10547                 d_printf("%s: second gencache_del() succeeded\n",
10548                          __location__);
10549                 return False;
10550         }
10551
10552         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10553                 d_printf("%s: gencache_get_data_blob() on deleted entry "
10554                          "succeeded\n", __location__);
10555                 return False;
10556         }
10557
10558         v = 1;
10559         blob.data = (uint8_t *)&v;
10560         blob.length = sizeof(v);
10561
10562         if (!gencache_set_data_blob("blob", blob, tm)) {
10563                 d_printf("%s: gencache_set_data_blob() failed\n",
10564                          __location__);
10565                 return false;
10566         }
10567         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
10568                 d_printf("%s: gencache_get succeeded\n", __location__);
10569                 return false;
10570         }
10571
10572         return True;
10573 }
10574
10575 static bool rbt_testval(struct db_context *db, const char *key,
10576                         const char *value)
10577 {
10578         struct db_record *rec;
10579         TDB_DATA data = string_tdb_data(value);
10580         bool ret = false;
10581         NTSTATUS status;
10582         TDB_DATA dbvalue;
10583
10584         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10585         if (rec == NULL) {
10586                 d_fprintf(stderr, "fetch_locked failed\n");
10587                 goto done;
10588         }
10589         status = dbwrap_record_store(rec, data, 0);
10590         if (!NT_STATUS_IS_OK(status)) {
10591                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
10592                 goto done;
10593         }
10594         TALLOC_FREE(rec);
10595
10596         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10597         if (rec == NULL) {
10598                 d_fprintf(stderr, "second fetch_locked failed\n");
10599                 goto done;
10600         }
10601
10602         dbvalue = dbwrap_record_get_value(rec);
10603         if ((dbvalue.dsize != data.dsize)
10604             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
10605                 d_fprintf(stderr, "Got wrong data back\n");
10606                 goto done;
10607         }
10608
10609         ret = true;
10610  done:
10611         TALLOC_FREE(rec);
10612         return ret;
10613 }
10614
10615 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
10616 {
10617         int *count2 = (int *)private_data;
10618         (*count2)++;
10619         return 0;
10620 }
10621
10622 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10623 {
10624         int *count2 = (int *)private_data;
10625         (*count2)++;
10626         dbwrap_record_delete(rec);
10627         return 0;
10628 }
10629
10630 static bool run_local_rbtree(int dummy)
10631 {
10632         struct db_context *db;
10633         bool ret = false;
10634         int i;
10635         NTSTATUS status;
10636         int count = 0;
10637         int count2 = 0;
10638
10639         db = db_open_rbt(NULL);
10640
10641         if (db == NULL) {
10642                 d_fprintf(stderr, "db_open_rbt failed\n");
10643                 return false;
10644         }
10645
10646         for (i=0; i<1000; i++) {
10647                 char *key, *value;
10648
10649                 if (asprintf(&key, "key%ld", random()) == -1) {
10650                         goto done;
10651                 }
10652                 if (asprintf(&value, "value%ld", random()) == -1) {
10653                         SAFE_FREE(key);
10654                         goto done;
10655                 }
10656
10657                 if (!rbt_testval(db, key, value)) {
10658                         SAFE_FREE(key);
10659                         SAFE_FREE(value);
10660                         goto done;
10661                 }
10662
10663                 SAFE_FREE(value);
10664                 if (asprintf(&value, "value%ld", random()) == -1) {
10665                         SAFE_FREE(key);
10666                         goto done;
10667                 }
10668
10669                 if (!rbt_testval(db, key, value)) {
10670                         SAFE_FREE(key);
10671                         SAFE_FREE(value);
10672                         goto done;
10673                 }
10674
10675                 SAFE_FREE(key);
10676                 SAFE_FREE(value);
10677         }
10678
10679         ret = true;
10680         count = 0; count2 = 0;
10681         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10682                                       &count2, &count);
10683         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10684         if ((count != count2) || (count != 1000)) {
10685                 ret = false;
10686         }
10687         count = 0; count2 = 0;
10688         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10689                                  &count2, &count);
10690         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10691         if ((count != count2) || (count != 1000)) {
10692                 ret = false;
10693         }
10694         count = 0; count2 = 0;
10695         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10696                                       &count2, &count);
10697         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10698         if ((count != count2) || (count != 0)) {
10699                 ret = false;
10700         }
10701
10702  done:
10703         TALLOC_FREE(db);
10704         return ret;
10705 }
10706
10707
10708 /*
10709   local test for character set functions
10710
10711   This is a very simple test for the functionality in convert_string_error()
10712  */
10713 static bool run_local_convert_string(int dummy)
10714 {
10715         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10716         const char *test_strings[2] = { "March", "M\303\244rz" };
10717         char dst[7];
10718         int i;
10719
10720         for (i=0; i<2; i++) {
10721                 const char *str = test_strings[i];
10722                 int len = strlen(str);
10723                 size_t converted_size;
10724                 bool ret;
10725
10726                 memset(dst, 'X', sizeof(dst));
10727
10728                 /* first try with real source length */
10729                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10730                                            str, len,
10731                                            dst, sizeof(dst),
10732                                            &converted_size);
10733                 if (ret != true) {
10734                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10735                         goto failed;
10736                 }
10737
10738                 if (converted_size != len) {
10739                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10740                                   str, len, (int)converted_size);
10741                         goto failed;
10742                 }
10743
10744                 if (strncmp(str, dst, converted_size) != 0) {
10745                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10746                         goto failed;
10747                 }
10748
10749                 if (strlen(str) != converted_size) {
10750                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10751                                   (int)strlen(str), (int)converted_size);
10752                         goto failed;
10753                 }
10754
10755                 if (dst[converted_size] != 'X') {
10756                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10757                         goto failed;
10758                 }
10759
10760                 /* now with srclen==-1, this causes the nul to be
10761                  * converted too */
10762                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10763                                            str, -1,
10764                                            dst, sizeof(dst),
10765                                            &converted_size);
10766                 if (ret != true) {
10767                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10768                         goto failed;
10769                 }
10770
10771                 if (converted_size != len+1) {
10772                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10773                                   str, len, (int)converted_size);
10774                         goto failed;
10775                 }
10776
10777                 if (strncmp(str, dst, converted_size) != 0) {
10778                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10779                         goto failed;
10780                 }
10781
10782                 if (len+1 != converted_size) {
10783                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10784                                   len+1, (int)converted_size);
10785                         goto failed;
10786                 }
10787
10788                 if (dst[converted_size] != 'X') {
10789                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10790                         goto failed;
10791                 }
10792
10793         }
10794
10795
10796         TALLOC_FREE(tmp_ctx);
10797         return true;
10798 failed:
10799         TALLOC_FREE(tmp_ctx);
10800         return false;
10801 }
10802
10803 static bool run_local_string_to_sid(int dummy) {
10804         struct dom_sid sid;
10805
10806         if (string_to_sid(&sid, "S--1-5-32-545")) {
10807                 printf("allowing S--1-5-32-545\n");
10808                 return false;
10809         }
10810         if (string_to_sid(&sid, "S-1-5-32-+545")) {
10811                 printf("allowing S-1-5-32-+545\n");
10812                 return false;
10813         }
10814         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")) {
10815                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10816                 return false;
10817         }
10818         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10819                 printf("allowing S-1-5-32-545-abc\n");
10820                 return false;
10821         }
10822         if (string_to_sid(&sid, "S-300-5-32-545")) {
10823                 printf("allowing S-300-5-32-545\n");
10824                 return false;
10825         }
10826         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10827                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10828                 return false;
10829         }
10830         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10831                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10832                 return false;
10833         }
10834         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10835                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10836                 return false;
10837         }
10838         if (!string_to_sid(&sid, "S-1-5-32-545")) {
10839                 printf("could not parse S-1-5-32-545\n");
10840                 return false;
10841         }
10842         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10843                 struct dom_sid_buf buf;
10844                 printf("mis-parsed S-1-5-32-545 as %s\n",
10845                        dom_sid_str_buf(&sid, &buf));
10846                 return false;
10847         }
10848         return true;
10849 }
10850
10851 static bool sid_to_string_test(const char *expected) {
10852         char *str;
10853         bool res = true;
10854         struct dom_sid sid;
10855
10856         if (!string_to_sid(&sid, expected)) {
10857                 printf("could not parse %s\n", expected);
10858                 return false;
10859         }
10860
10861         str = dom_sid_string(NULL, &sid);
10862         if (strcmp(str, expected)) {
10863                 printf("Comparison failed (%s != %s)\n", str, expected);
10864                 res = false;
10865         }
10866         TALLOC_FREE(str);
10867         return res;
10868 }
10869
10870 static bool run_local_sid_to_string(int dummy) {
10871         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10872                 return false;
10873         if (!sid_to_string_test("S-1-545"))
10874                 return false;
10875         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10876                 return false;
10877         return true;
10878 }
10879
10880 static bool run_local_binary_to_sid(int dummy) {
10881         struct sid_parse_ret ret;
10882         struct dom_sid *sid = talloc(NULL, struct dom_sid);
10883         static const uint8_t good_binary_sid[] = {
10884                 0x1, /* revision number */
10885                 15, /* num auths */
10886                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10887                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10888                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10889                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10890                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10891                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10892                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10893                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10894                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10895                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10896                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10897                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10898                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10899                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10900                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10901                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10902         };
10903
10904         static const uint8_t long_binary_sid[] = {
10905                 0x1, /* revision number */
10906                 15, /* num auths */
10907                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10908                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10909                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10910                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10911                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10912                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10913                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10914                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10915                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10916                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10917                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10918                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10919                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10920                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10921                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10922                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10923                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10924                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10925                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10926         };
10927
10928         static const uint8_t long_binary_sid2[] = {
10929                 0x1, /* revision number */
10930                 32, /* num auths */
10931                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10932                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10933                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10934                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10935                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10936                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10937                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10938                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10939                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10940                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10941                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10942                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10943                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10944                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10945                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10946                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10947                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10948                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10949                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10950                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10951                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10952                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10953                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10954                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10955                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10956                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10957                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10958                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10959                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10960                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10961                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10962                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10963                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10964         };
10965
10966         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
10967         if (ret.len == -1) {
10968                 return false;
10969         }
10970         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
10971         if (ret.len != -1) {
10972                 return false;
10973         }
10974         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
10975         if (ret.len != -1) {
10976                 return false;
10977         }
10978         return true;
10979 }
10980
10981 /* Split a path name into filename and stream name components. Canonicalise
10982  * such that an implicit $DATA token is always explicit.
10983  *
10984  * The "specification" of this function can be found in the
10985  * run_local_stream_name() function in torture.c, I've tried those
10986  * combinations against a W2k3 server.
10987  */
10988
10989 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10990                                        char **pbase, char **pstream)
10991 {
10992         char *base = NULL;
10993         char *stream = NULL;
10994         char *sname; /* stream name */
10995         const char *stype; /* stream type */
10996
10997         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
10998
10999         sname = strchr_m(fname, ':');
11000
11001         if (sname == NULL) {
11002                 if (pbase != NULL) {
11003                         base = talloc_strdup(mem_ctx, fname);
11004                         NT_STATUS_HAVE_NO_MEMORY(base);
11005                 }
11006                 goto done;
11007         }
11008
11009         if (pbase != NULL) {
11010                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
11011                 NT_STATUS_HAVE_NO_MEMORY(base);
11012         }
11013
11014         sname += 1;
11015
11016         stype = strchr_m(sname, ':');
11017
11018         if (stype == NULL) {
11019                 sname = talloc_strdup(mem_ctx, sname);
11020                 stype = "$DATA";
11021         }
11022         else {
11023                 if (strcasecmp_m(stype, ":$DATA") != 0) {
11024                         /*
11025                          * If there is an explicit stream type, so far we only
11026                          * allow $DATA. Is there anything else allowed? -- vl
11027                          */
11028                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
11029                         TALLOC_FREE(base);
11030                         return NT_STATUS_OBJECT_NAME_INVALID;
11031                 }
11032                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
11033                 stype += 1;
11034         }
11035
11036         if (sname == NULL) {
11037                 TALLOC_FREE(base);
11038                 return NT_STATUS_NO_MEMORY;
11039         }
11040
11041         if (sname[0] == '\0') {
11042                 /*
11043                  * no stream name, so no stream
11044                  */
11045                 goto done;
11046         }
11047
11048         if (pstream != NULL) {
11049                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
11050                 if (stream == NULL) {
11051                         TALLOC_FREE(sname);
11052                         TALLOC_FREE(base);
11053                         return NT_STATUS_NO_MEMORY;
11054                 }
11055                 /*
11056                  * upper-case the type field
11057                  */
11058                 (void)strupper_m(strchr_m(stream, ':')+1);
11059         }
11060
11061  done:
11062         if (pbase != NULL) {
11063                 *pbase = base;
11064         }
11065         if (pstream != NULL) {
11066                 *pstream = stream;
11067         }
11068         return NT_STATUS_OK;
11069 }
11070
11071 static bool test_stream_name(const char *fname, const char *expected_base,
11072                              const char *expected_stream,
11073                              NTSTATUS expected_status)
11074 {
11075         NTSTATUS status;
11076         char *base = NULL;
11077         char *stream = NULL;
11078
11079         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
11080         if (!NT_STATUS_EQUAL(status, expected_status)) {
11081                 goto error;
11082         }
11083
11084         if (!NT_STATUS_IS_OK(status)) {
11085                 return true;
11086         }
11087
11088         if (base == NULL) goto error;
11089
11090         if (strcmp(expected_base, base) != 0) goto error;
11091
11092         if ((expected_stream != NULL) && (stream == NULL)) goto error;
11093         if ((expected_stream == NULL) && (stream != NULL)) goto error;
11094
11095         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
11096                 goto error;
11097
11098         TALLOC_FREE(base);
11099         TALLOC_FREE(stream);
11100         return true;
11101
11102  error:
11103         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
11104                   fname, expected_base ? expected_base : "<NULL>",
11105                   expected_stream ? expected_stream : "<NULL>",
11106                   nt_errstr(expected_status));
11107         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
11108                   base ? base : "<NULL>", stream ? stream : "<NULL>",
11109                   nt_errstr(status));
11110         TALLOC_FREE(base);
11111         TALLOC_FREE(stream);
11112         return false;
11113 }
11114
11115 static bool run_local_stream_name(int dummy)
11116 {
11117         bool ret = true;
11118
11119         ret &= test_stream_name(
11120                 "bla", "bla", NULL, NT_STATUS_OK);
11121         ret &= test_stream_name(
11122                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
11123         ret &= test_stream_name(
11124                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
11125         ret &= test_stream_name(
11126                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
11127         ret &= test_stream_name(
11128                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
11129         ret &= test_stream_name(
11130                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
11131         ret &= test_stream_name(
11132                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
11133         ret &= test_stream_name(
11134                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
11135
11136         return ret;
11137 }
11138
11139 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
11140 {
11141         if (a.length != b.length) {
11142                 printf("a.length=%d != b.length=%d\n",
11143                        (int)a.length, (int)b.length);
11144                 return false;
11145         }
11146         if (memcmp(a.data, b.data, a.length) != 0) {
11147                 printf("a.data and b.data differ\n");
11148                 return false;
11149         }
11150         return true;
11151 }
11152
11153 static bool run_local_memcache(int dummy)
11154 {
11155         struct memcache *cache;
11156         DATA_BLOB k1, k2, k3;
11157         DATA_BLOB d1, d3;
11158         DATA_BLOB v1, v3;
11159
11160         TALLOC_CTX *mem_ctx;
11161         char *ptr1 = NULL;
11162         char *ptr2 = NULL;
11163
11164         char *str1, *str2;
11165         size_t size1, size2;
11166         bool ret = false;
11167
11168         mem_ctx = talloc_init("foo");
11169         if (mem_ctx == NULL) {
11170                 return false;
11171         }
11172
11173         /* STAT_CACHE TESTS */
11174
11175         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
11176
11177         if (cache == NULL) {
11178                 printf("memcache_init failed\n");
11179                 return false;
11180         }
11181
11182         d1 = data_blob_const("d1", 2);
11183         d3 = data_blob_const("d3", 2);
11184
11185         k1 = data_blob_const("d1", 2);
11186         k2 = data_blob_const("d2", 2);
11187         k3 = data_blob_const("d3", 2);
11188
11189         memcache_add(cache, STAT_CACHE, k1, d1);
11190
11191         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
11192                 printf("could not find k1\n");
11193                 return false;
11194         }
11195         if (!data_blob_equal(d1, v1)) {
11196                 return false;
11197         }
11198
11199         memcache_add(cache, STAT_CACHE, k1, d3);
11200
11201         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
11202                 printf("could not find replaced k1\n");
11203                 return false;
11204         }
11205         if (!data_blob_equal(d3, v3)) {
11206                 return false;
11207         }
11208
11209         TALLOC_FREE(cache);
11210
11211         /* GETWD_CACHE TESTS */
11212         str1 = talloc_strdup(mem_ctx, "string1");
11213         if (str1 == NULL) {
11214                 return false;
11215         }
11216         ptr2 = str1; /* Keep an alias for comparison. */
11217
11218         str2 = talloc_strdup(mem_ctx, "string2");
11219         if (str2 == NULL) {
11220                 return false;
11221         }
11222
11223         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
11224         if (cache == NULL) {
11225                 printf("memcache_init failed\n");
11226                 return false;
11227         }
11228
11229         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
11230         /* str1 == NULL now. */
11231         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
11232         if (ptr1 == NULL) {
11233                 printf("could not find k2\n");
11234                 return false;
11235         }
11236         if (ptr1 != ptr2) {
11237                 printf("fetch of k2 got wrong string\n");
11238                 return false;
11239         }
11240
11241         /* Add a blob to ensure k2 gets purged. */
11242         d3 = data_blob_talloc_zero(mem_ctx, 180);
11243         memcache_add(cache, STAT_CACHE, k3, d3);
11244
11245         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
11246         if (ptr2 != NULL) {
11247                 printf("Did find k2, should have been purged\n");
11248                 return false;
11249         }
11250
11251         TALLOC_FREE(cache);
11252         TALLOC_FREE(mem_ctx);
11253
11254         mem_ctx = talloc_init("foo");
11255         if (mem_ctx == NULL) {
11256                 return false;
11257         }
11258
11259         cache = memcache_init(NULL, 0);
11260         if (cache == NULL) {
11261                 return false;
11262         }
11263
11264         str1 = talloc_strdup(mem_ctx, "string1");
11265         if (str1 == NULL) {
11266                 return false;
11267         }
11268         str2 = talloc_strdup(mem_ctx, "string2");
11269         if (str2 == NULL) {
11270                 return false;
11271         }
11272         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
11273                             data_blob_string_const("torture"), &str1);
11274         size1 = talloc_total_size(cache);
11275
11276         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
11277                             data_blob_string_const("torture"), &str2);
11278         size2 = talloc_total_size(cache);
11279
11280         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
11281
11282         if (size2 > size1) {
11283                 printf("memcache leaks memory!\n");
11284                 goto fail;
11285         }
11286
11287         ret = true;
11288  fail:
11289         TALLOC_FREE(cache);
11290         return ret;
11291 }
11292
11293 static void wbclient_done(struct tevent_req *req)
11294 {
11295         wbcErr wbc_err;
11296         struct winbindd_response *wb_resp;
11297         int *i = (int *)tevent_req_callback_data_void(req);
11298
11299         wbc_err = wb_trans_recv(req, req, &wb_resp);
11300         TALLOC_FREE(req);
11301         *i += 1;
11302         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
11303 }
11304
11305 static bool run_wbclient_multi_ping(int dummy)
11306 {
11307         struct tevent_context *ev;
11308         struct wb_context **wb_ctx;
11309         struct winbindd_request wb_req;
11310         bool result = false;
11311         int i, j;
11312
11313         BlockSignals(True, SIGPIPE);
11314
11315         ev = tevent_context_init(talloc_tos());
11316         if (ev == NULL) {
11317                 goto fail;
11318         }
11319
11320         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
11321         if (wb_ctx == NULL) {
11322                 goto fail;
11323         }
11324
11325         ZERO_STRUCT(wb_req);
11326         wb_req.cmd = WINBINDD_PING;
11327
11328         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
11329
11330         for (i=0; i<torture_nprocs; i++) {
11331                 wb_ctx[i] = wb_context_init(ev, NULL);
11332                 if (wb_ctx[i] == NULL) {
11333                         goto fail;
11334                 }
11335                 for (j=0; j<torture_numops; j++) {
11336                         struct tevent_req *req;
11337                         req = wb_trans_send(ev, ev, wb_ctx[i],
11338                                             (j % 2) == 0, &wb_req);
11339                         if (req == NULL) {
11340                                 goto fail;
11341                         }
11342                         tevent_req_set_callback(req, wbclient_done, &i);
11343                 }
11344         }
11345
11346         i = 0;
11347
11348         while (i < torture_nprocs * torture_numops) {
11349                 tevent_loop_once(ev);
11350         }
11351
11352         result = true;
11353  fail:
11354         TALLOC_FREE(ev);
11355         return result;
11356 }
11357
11358 static bool dbtrans_inc(struct db_context *db)
11359 {
11360         struct db_record *rec;
11361         uint32_t val;
11362         bool ret = false;
11363         NTSTATUS status;
11364         TDB_DATA value;
11365
11366         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11367         if (rec == NULL) {
11368                 printf(__location__ "fetch_lock failed\n");
11369                 return false;
11370         }
11371
11372         value = dbwrap_record_get_value(rec);
11373
11374         if (value.dsize != sizeof(uint32_t)) {
11375                 printf(__location__ "value.dsize = %d\n",
11376                        (int)value.dsize);
11377                 goto fail;
11378         }
11379
11380         memcpy(&val, value.dptr, sizeof(val));
11381         val += 1;
11382
11383         status = dbwrap_record_store(
11384                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
11385         if (!NT_STATUS_IS_OK(status)) {
11386                 printf(__location__ "store failed: %s\n",
11387                        nt_errstr(status));
11388                 goto fail;
11389         }
11390
11391         ret = true;
11392 fail:
11393         TALLOC_FREE(rec);
11394         return ret;
11395 }
11396
11397 static bool run_local_dbtrans(int dummy)
11398 {
11399         struct db_context *db;
11400         struct db_record *rec;
11401         NTSTATUS status;
11402         uint32_t initial;
11403         int res;
11404         TDB_DATA value;
11405
11406         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
11407                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
11408                      DBWRAP_FLAG_NONE);
11409         if (db == NULL) {
11410                 printf("Could not open transtest.db\n");
11411                 return false;
11412         }
11413
11414         res = dbwrap_transaction_start(db);
11415         if (res != 0) {
11416                 printf(__location__ "transaction_start failed\n");
11417                 return false;
11418         }
11419
11420         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11421         if (rec == NULL) {
11422                 printf(__location__ "fetch_lock failed\n");
11423                 return false;
11424         }
11425
11426         value = dbwrap_record_get_value(rec);
11427
11428         if (value.dptr == NULL) {
11429                 initial = 0;
11430                 status = dbwrap_record_store(
11431                         rec, make_tdb_data((uint8_t *)&initial,
11432                                            sizeof(initial)),
11433                         0);
11434                 if (!NT_STATUS_IS_OK(status)) {
11435                         printf(__location__ "store returned %s\n",
11436                                nt_errstr(status));
11437                         return false;
11438                 }
11439         }
11440
11441         TALLOC_FREE(rec);
11442
11443         res = dbwrap_transaction_commit(db);
11444         if (res != 0) {
11445                 printf(__location__ "transaction_commit failed\n");
11446                 return false;
11447         }
11448
11449         while (true) {
11450                 uint32_t val, val2;
11451                 int i;
11452
11453                 res = dbwrap_transaction_start(db);
11454                 if (res != 0) {
11455                         printf(__location__ "transaction_start failed\n");
11456                         break;
11457                 }
11458
11459                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
11460                 if (!NT_STATUS_IS_OK(status)) {
11461                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11462                                nt_errstr(status));
11463                         break;
11464                 }
11465
11466                 for (i=0; i<10; i++) {
11467                         if (!dbtrans_inc(db)) {
11468                                 return false;
11469                         }
11470                 }
11471
11472                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
11473                 if (!NT_STATUS_IS_OK(status)) {
11474                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11475                                nt_errstr(status));
11476                         break;
11477                 }
11478
11479                 if (val2 != val + 10) {
11480                         printf(__location__ "val=%d, val2=%d\n",
11481                                (int)val, (int)val2);
11482                         break;
11483                 }
11484
11485                 printf("val2=%d\r", val2);
11486
11487                 res = dbwrap_transaction_commit(db);
11488                 if (res != 0) {
11489                         printf(__location__ "transaction_commit failed\n");
11490                         break;
11491                 }
11492         }
11493
11494         TALLOC_FREE(db);
11495         return true;
11496 }
11497
11498 /*
11499  * Just a dummy test to be run under a debugger. There's no real way
11500  * to inspect the tevent_poll specific function from outside of
11501  * tevent_poll.c.
11502  */
11503
11504 static bool run_local_tevent_poll(int dummy)
11505 {
11506         struct tevent_context *ev;
11507         struct tevent_fd *fd1, *fd2;
11508         bool result = false;
11509
11510         ev = tevent_context_init_byname(NULL, "poll");
11511         if (ev == NULL) {
11512                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
11513                 goto fail;
11514         }
11515
11516         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
11517         if (fd1 == NULL) {
11518                 d_fprintf(stderr, "tevent_add_fd failed\n");
11519                 goto fail;
11520         }
11521         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
11522         if (fd2 == NULL) {
11523                 d_fprintf(stderr, "tevent_add_fd failed\n");
11524                 goto fail;
11525         }
11526         TALLOC_FREE(fd2);
11527
11528         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
11529         if (fd2 == NULL) {
11530                 d_fprintf(stderr, "tevent_add_fd failed\n");
11531                 goto fail;
11532         }
11533
11534         result = true;
11535 fail:
11536         TALLOC_FREE(ev);
11537         return result;
11538 }
11539
11540 static bool run_local_hex_encode_buf(int dummy)
11541 {
11542         char buf[17];
11543         uint8_t src[8];
11544         int i;
11545
11546         for (i=0; i<sizeof(src); i++) {
11547                 src[i] = i;
11548         }
11549         hex_encode_buf(buf, src, sizeof(src));
11550         if (strcmp(buf, "0001020304050607") != 0) {
11551                 return false;
11552         }
11553         hex_encode_buf(buf, NULL, 0);
11554         if (buf[0] != '\0') {
11555                 return false;
11556         }
11557         return true;
11558 }
11559
11560 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
11561         "0.0.0.0",
11562         "::0",
11563         "1.2.3.1",
11564         "0.0.0.0",
11565         "0.0.0.0",
11566         "1.2.3.2",
11567         "1.2.3.3",
11568         "1.2.3.4",
11569         "1.2.3.5",
11570         "::0",
11571         "1.2.3.6",
11572         "1.2.3.7",
11573         "::0",
11574         "::0",
11575         "::0",
11576         "1.2.3.8",
11577         "1.2.3.9",
11578         "1.2.3.10",
11579         "1.2.3.11",
11580         "1.2.3.12",
11581         "1.2.3.13",
11582         "1001:1111:1111:1000:0:1111:1111:1111",
11583         "1.2.3.1",
11584         "1.2.3.2",
11585         "1.2.3.3",
11586         "1.2.3.12",
11587         "::0",
11588         "::0"
11589 };
11590
11591 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11592         "1.2.3.1",
11593         "1.2.3.2",
11594         "1.2.3.3",
11595         "1.2.3.4",
11596         "1.2.3.5",
11597         "1.2.3.6",
11598         "1.2.3.7",
11599         "1.2.3.8",
11600         "1.2.3.9",
11601         "1.2.3.10",
11602         "1.2.3.11",
11603         "1.2.3.12",
11604         "1.2.3.13",
11605         "1001:1111:1111:1000:0:1111:1111:1111"
11606 };
11607
11608 static bool run_local_remove_duplicate_addrs2(int dummy)
11609 {
11610         struct ip_service test_vector[28];
11611         int count, i;
11612
11613         /* Construct the sockaddr_storage test vector. */
11614         for (i = 0; i < 28; i++) {
11615                 struct addrinfo hints;
11616                 struct addrinfo *res = NULL;
11617                 int ret;
11618
11619                 memset(&hints, '\0', sizeof(hints));
11620                 hints.ai_flags = AI_NUMERICHOST;
11621                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11622                                 NULL,
11623                                 &hints,
11624                                 &res);
11625                 if (ret) {
11626                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
11627                                 remove_duplicate_addrs2_test_strings_vector[i]);
11628                         return false;
11629                 }
11630                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11631                 memcpy(&test_vector[i].ss,
11632                         res->ai_addr,
11633                         res->ai_addrlen);
11634                 freeaddrinfo(res);
11635         }
11636
11637         count = remove_duplicate_addrs2(test_vector, i);
11638
11639         if (count != 14) {
11640                 fprintf(stderr, "count wrong (%d) should be 14\n",
11641                         count);
11642                 return false;
11643         }
11644
11645         for (i = 0; i < count; i++) {
11646                 char addr[INET6_ADDRSTRLEN];
11647
11648                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11649
11650                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11651                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11652                                 i,
11653                                 addr,
11654                                 remove_duplicate_addrs2_test_strings_result[i]);
11655                         return false;
11656                 }
11657         }
11658
11659         printf("run_local_remove_duplicate_addrs2: success\n");
11660         return true;
11661 }
11662
11663 static bool run_local_tdb_opener(int dummy)
11664 {
11665         TDB_CONTEXT *t;
11666         unsigned v = 0;
11667
11668         while (1) {
11669                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11670                              O_RDWR|O_CREAT, 0755);
11671                 if (t == NULL) {
11672                         perror("tdb_open failed");
11673                         return false;
11674                 }
11675                 tdb_close(t);
11676
11677                 v += 1;
11678                 printf("\r%u", v);
11679         }
11680         return true;
11681 }
11682
11683 static bool run_local_tdb_writer(int dummy)
11684 {
11685         TDB_CONTEXT *t;
11686         unsigned v = 0;
11687         TDB_DATA val;
11688
11689         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11690         if (t == 0) {
11691                 perror("tdb_open failed");
11692                 return 1;
11693         }
11694
11695         val.dptr = (uint8_t *)&v;
11696         val.dsize = sizeof(v);
11697
11698         while (1) {
11699                 TDB_DATA data;
11700                 int ret;
11701
11702                 ret = tdb_store(t, val, val, 0);
11703                 if (ret != 0) {
11704                         printf("%s\n", tdb_errorstr(t));
11705                 }
11706                 v += 1;
11707                 printf("\r%u", v);
11708
11709                 data = tdb_fetch(t, val);
11710                 if (data.dptr != NULL) {
11711                         SAFE_FREE(data.dptr);
11712                 }
11713         }
11714         return true;
11715 }
11716
11717 static bool run_local_canonicalize_path(int dummy)
11718 {
11719         const char *src[] = {
11720                         "/foo/..",
11721                         "/..",
11722                         "/foo/bar/../baz",
11723                         "/foo/././",
11724                         "/../foo",
11725                         ".././././",
11726                         ".././././../../../boo",
11727                         "./..",
11728                         NULL
11729                         };
11730         const char *dst[] = {
11731                         "/",
11732                         "/",
11733                         "/foo/baz",
11734                         "/foo",
11735                         "/foo",
11736                         "/",
11737                         "/boo",
11738                         "/",
11739                         NULL
11740                         };
11741         unsigned int i;
11742
11743         for (i = 0; src[i] != NULL; i++) {
11744                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11745                 if (d == NULL) {
11746                         perror("talloc fail\n");
11747                         return false;
11748                 }
11749                 if (strcmp(d, dst[i]) != 0) {
11750                         d_fprintf(stderr,
11751                                 "canonicalize mismatch %s -> %s != %s",
11752                                 src[i], d, dst[i]);
11753                         return false;
11754                 }
11755                 talloc_free(d);
11756         }
11757         return true;
11758 }
11759
11760 static bool run_ign_bad_negprot(int dummy)
11761 {
11762         struct tevent_context *ev;
11763         struct tevent_req *req;
11764         struct smbXcli_conn *conn;
11765         struct sockaddr_storage ss;
11766         NTSTATUS status;
11767         int fd;
11768         bool ok;
11769
11770         printf("starting ignore bad negprot\n");
11771
11772         ok = resolve_name(host, &ss, 0x20, true);
11773         if (!ok) {
11774                 d_fprintf(stderr, "Could not resolve name %s\n", host);
11775                 return false;
11776         }
11777
11778         status = open_socket_out(&ss, 445, 10000, &fd);
11779         if (!NT_STATUS_IS_OK(status)) {
11780                 d_fprintf(stderr, "open_socket_out failed: %s\n",
11781                           nt_errstr(status));
11782                 return false;
11783         }
11784
11785         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11786                                    NULL, 0);
11787         if (conn == NULL) {
11788                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11789                 return false;
11790         }
11791
11792         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11793         if (NT_STATUS_IS_OK(status)) {
11794                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11795                 return false;
11796         }
11797
11798         ev = samba_tevent_context_init(talloc_tos());
11799         if (ev == NULL) {
11800                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11801                 return false;
11802         }
11803
11804         req = smb1cli_session_setup_nt1_send(
11805                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11806                 data_blob_null, data_blob_null, 0x40,
11807                 "Windows 2000 2195", "Windows 2000 5.0");
11808         if (req == NULL) {
11809                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11810                 return false;
11811         }
11812
11813         ok = tevent_req_poll_ntstatus(req, ev, &status);
11814         if (!ok) {
11815                 d_fprintf(stderr, "tevent_req_poll failed\n");
11816                 return false;
11817         }
11818
11819         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11820                                                 NULL, NULL);
11821         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11822                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11823                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
11824                           nt_errstr(status));
11825                 return false;
11826         }
11827
11828         TALLOC_FREE(conn);
11829
11830         printf("starting ignore bad negprot\n");
11831
11832         return true;
11833 }
11834
11835 static double create_procs(bool (*fn)(int), bool *result)
11836 {
11837         int i, status;
11838         volatile pid_t *child_status;
11839         volatile bool *child_status_out;
11840         int synccount;
11841         int tries = 8;
11842         struct timeval start;
11843
11844         synccount = 0;
11845
11846         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11847         if (!child_status) {
11848                 printf("Failed to setup shared memory\n");
11849                 return -1;
11850         }
11851
11852         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11853         if (!child_status_out) {
11854                 printf("Failed to setup result status shared memory\n");
11855                 return -1;
11856         }
11857
11858         for (i = 0; i < torture_nprocs; i++) {
11859                 child_status[i] = 0;
11860                 child_status_out[i] = True;
11861         }
11862
11863         start = timeval_current();
11864
11865         for (i=0;i<torture_nprocs;i++) {
11866                 procnum = i;
11867                 if (fork() == 0) {
11868                         pid_t mypid = getpid();
11869                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11870
11871                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
11872
11873                         while (1) {
11874                                 if (torture_open_connection(&current_cli, i)) break;
11875                                 if (tries-- == 0) {
11876                                         printf("pid %d failed to start\n", (int)getpid());
11877                                         _exit(1);
11878                                 }
11879                                 smb_msleep(10); 
11880                         }
11881
11882                         child_status[i] = getpid();
11883
11884                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11885
11886                         child_status_out[i] = fn(i);
11887                         _exit(0);
11888                 }
11889         }
11890
11891         do {
11892                 synccount = 0;
11893                 for (i=0;i<torture_nprocs;i++) {
11894                         if (child_status[i]) synccount++;
11895                 }
11896                 if (synccount == torture_nprocs) break;
11897                 smb_msleep(10);
11898         } while (timeval_elapsed(&start) < 30);
11899
11900         if (synccount != torture_nprocs) {
11901                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11902                 *result = False;
11903                 return timeval_elapsed(&start);
11904         }
11905
11906         /* start the client load */
11907         start = timeval_current();
11908
11909         for (i=0;i<torture_nprocs;i++) {
11910                 child_status[i] = 0;
11911         }
11912
11913         printf("%d clients started\n", torture_nprocs);
11914
11915         for (i=0;i<torture_nprocs;i++) {
11916                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11917         }
11918
11919         printf("\n");
11920
11921         for (i=0;i<torture_nprocs;i++) {
11922                 if (!child_status_out[i]) {
11923                         *result = False;
11924                 }
11925         }
11926         return timeval_elapsed(&start);
11927 }
11928
11929 #define FLAG_MULTIPROC 1
11930
11931 static struct {
11932         const char *name;
11933         bool (*fn)(int);
11934         unsigned flags;
11935 } torture_ops[] = {
11936         {
11937                 .name = "FDPASS",
11938                 .fn   = run_fdpasstest,
11939         },
11940         {
11941                 .name = "LOCK1",
11942                 .fn   = run_locktest1,
11943         },
11944         {
11945                 .name = "LOCK2",
11946                 .fn   =  run_locktest2,
11947         },
11948         {
11949                 .name = "LOCK3",
11950                 .fn   =  run_locktest3,
11951         },
11952         {
11953                 .name = "LOCK4",
11954                 .fn   =  run_locktest4,
11955         },
11956         {
11957                 .name = "LOCK5",
11958                 .fn   =  run_locktest5,
11959         },
11960         {
11961                 .name = "LOCK6",
11962                 .fn   =  run_locktest6,
11963         },
11964         {
11965                 .name = "LOCK7",
11966                 .fn   =  run_locktest7,
11967         },
11968         {
11969                 .name = "LOCK8",
11970                 .fn   =  run_locktest8,
11971         },
11972         {
11973                 .name = "LOCK9",
11974                 .fn   =  run_locktest9,
11975         },
11976         {
11977                 .name = "UNLINK",
11978                 .fn   = run_unlinktest,
11979         },
11980         {
11981                 .name = "BROWSE",
11982                 .fn   = run_browsetest,
11983         },
11984         {
11985                 .name = "ATTR",
11986                 .fn   =   run_attrtest,
11987         },
11988         {
11989                 .name = "TRANS2",
11990                 .fn   = run_trans2test,
11991         },
11992         {
11993                 .name  = "MAXFID",
11994                 .fn    = run_maxfidtest,
11995                 .flags = FLAG_MULTIPROC,
11996         },
11997         {
11998                 .name  = "TORTURE",
11999                 .fn    = run_torture,
12000                 .flags = FLAG_MULTIPROC,
12001         },
12002         {
12003                 .name  = "RANDOMIPC",
12004                 .fn    = run_randomipc,
12005         },
12006         {
12007                 .name  = "NEGNOWAIT",
12008                 .fn    = run_negprot_nowait,
12009         },
12010         {
12011                 .name  = "NBENCH",
12012                 .fn    =  run_nbench,
12013         },
12014         {
12015                 .name  = "NBENCH2",
12016                 .fn    = run_nbench2,
12017         },
12018         {
12019                 .name  = "OPLOCK1",
12020                 .fn    =  run_oplock1,
12021         },
12022         {
12023                 .name  = "OPLOCK2",
12024                 .fn    =  run_oplock2,
12025         },
12026         {
12027                 .name  = "OPLOCK4",
12028                 .fn    =  run_oplock4,
12029         },
12030         {
12031                 .name  = "DIR",
12032                 .fn    =  run_dirtest,
12033         },
12034         {
12035                 .name  = "DIR1",
12036                 .fn    =  run_dirtest1,
12037         },
12038         {
12039                 .name  = "DIR-CREATETIME",
12040                 .fn    =  run_dir_createtime,
12041         },
12042         {
12043                 .name  = "DENY1",
12044                 .fn    =  torture_denytest1,
12045         },
12046         {
12047                 .name  = "DENY2",
12048                 .fn    =  torture_denytest2,
12049         },
12050         {
12051                 .name  = "TCON",
12052                 .fn    =  run_tcon_test,
12053         },
12054         {
12055                 .name  = "TCONDEV",
12056                 .fn    =  run_tcon_devtype_test,
12057         },
12058         {
12059                 .name  = "RW1",
12060                 .fn    =  run_readwritetest,
12061         },
12062         {
12063                 .name  = "RW2",
12064                 .fn    =  run_readwritemulti,
12065                 .flags = FLAG_MULTIPROC
12066         },
12067         {
12068                 .name  = "RW3",
12069                 .fn    =  run_readwritelarge,
12070         },
12071         {
12072                 .name  = "RW-SIGNING",
12073                 .fn    =  run_readwritelarge_signtest,
12074         },
12075         {
12076                 .name  = "OPEN",
12077                 .fn    = run_opentest,
12078         },
12079         {
12080                 .name  = "POSIX",
12081                 .fn    = run_simple_posix_open_test,
12082         },
12083         {
12084                 .name  = "POSIX-APPEND",
12085                 .fn    = run_posix_append,
12086         },
12087         {
12088                 .name  = "POSIX-SYMLINK-ACL",
12089                 .fn    = run_acl_symlink_test,
12090         },
12091         {
12092                 .name  = "POSIX-SYMLINK-EA",
12093                 .fn    = run_ea_symlink_test,
12094         },
12095         {
12096                 .name  = "POSIX-STREAM-DELETE",
12097                 .fn    = run_posix_stream_delete,
12098         },
12099         {
12100                 .name  = "POSIX-OFD-LOCK",
12101                 .fn    = run_posix_ofd_lock_test,
12102         },
12103         {
12104                 .name  = "POSIX-MKDIR",
12105                 .fn    = run_posix_mkdir_test,
12106         },
12107         {
12108                 .name  = "WINDOWS-BAD-SYMLINK",
12109                 .fn    = run_symlink_open_test,
12110         },
12111         {
12112                 .name  = "CASE-INSENSITIVE-CREATE",
12113                 .fn    = run_case_insensitive_create,
12114         },
12115         {
12116                 .name  = "ASYNC-ECHO",
12117                 .fn    = run_async_echo,
12118         },
12119         {
12120                 .name  = "UID-REGRESSION-TEST",
12121                 .fn    = run_uid_regression_test,
12122         },
12123         {
12124                 .name  = "SHORTNAME-TEST",
12125                 .fn    = run_shortname_test,
12126         },
12127         {
12128                 .name  = "ADDRCHANGE",
12129                 .fn    = run_addrchange,
12130         },
12131 #if 1
12132         {
12133                 .name  = "OPENATTR",
12134                 .fn    = run_openattrtest,
12135         },
12136 #endif
12137         {
12138                 .name  = "XCOPY",
12139                 .fn    = run_xcopy,
12140         },
12141         {
12142                 .name  = "RENAME",
12143                 .fn    = run_rename,
12144         },
12145         {
12146                 .name  = "RENAME-ACCESS",
12147                 .fn    = run_rename_access,
12148         },
12149         {
12150                 .name  = "OWNER-RIGHTS",
12151                 .fn    = run_owner_rights,
12152         },
12153         {
12154                 .name  = "DELETE",
12155                 .fn    = run_deletetest,
12156         },
12157         {
12158                 .name  = "DELETE-PRINT",
12159                 .fn    = run_delete_print_test,
12160         },
12161         {
12162                 .name  = "WILDDELETE",
12163                 .fn    = run_wild_deletetest,
12164         },
12165         {
12166                 .name  = "DELETE-LN",
12167                 .fn    = run_deletetest_ln,
12168         },
12169         {
12170                 .name  = "PROPERTIES",
12171                 .fn    = run_properties,
12172         },
12173         {
12174                 .name  = "MANGLE",
12175                 .fn    = torture_mangle,
12176         },
12177         {
12178                 .name  = "MANGLE1",
12179                 .fn    = run_mangle1,
12180         },
12181         {
12182                 .name  = "MANGLE-ILLEGAL",
12183                 .fn    = run_mangle_illegal,
12184         },
12185         {
12186                 .name  = "W2K",
12187                 .fn    = run_w2ktest,
12188         },
12189         {
12190                 .name  = "TRANS2SCAN",
12191                 .fn    = torture_trans2_scan,
12192         },
12193         {
12194                 .name  = "NTTRANSSCAN",
12195                 .fn    = torture_nttrans_scan,
12196         },
12197         {
12198                 .name  = "UTABLE",
12199                 .fn    = torture_utable,
12200         },
12201         {
12202                 .name  = "CASETABLE",
12203                 .fn    = torture_casetable,
12204         },
12205         {
12206                 .name  = "ERRMAPEXTRACT",
12207                 .fn    = run_error_map_extract,
12208         },
12209         {
12210                 .name  = "PIPE_NUMBER",
12211                 .fn    = run_pipe_number,
12212         },
12213         {
12214                 .name  = "TCON2",
12215                 .fn    =  run_tcon2_test,
12216         },
12217         {
12218                 .name  = "IOCTL",
12219                 .fn    =  torture_ioctl_test,
12220         },
12221         {
12222                 .name  = "CHKPATH",
12223                 .fn    =  torture_chkpath_test,
12224         },
12225         {
12226                 .name  = "FDSESS",
12227                 .fn    = run_fdsesstest,
12228         },
12229         {
12230                 .name  = "EATEST",
12231                 .fn    = run_eatest,
12232         },
12233         {
12234                 .name  = "SESSSETUP_BENCH",
12235                 .fn    = run_sesssetup_bench,
12236         },
12237         {
12238                 .name  = "CHAIN1",
12239                 .fn    = run_chain1,
12240         },
12241         {
12242                 .name  = "CHAIN2",
12243                 .fn    = run_chain2,
12244         },
12245         {
12246                 .name  = "CHAIN3",
12247                 .fn    = run_chain3,
12248         },
12249         {
12250                 .name  = "WINDOWS-WRITE",
12251                 .fn    = run_windows_write,
12252         },
12253         {
12254                 .name  = "LARGE_READX",
12255                 .fn    = run_large_readx,
12256         },
12257         {
12258                 .name  = "NTTRANS-CREATE",
12259                 .fn    = run_nttrans_create,
12260         },
12261         {
12262                 .name  = "NTTRANS-FSCTL",
12263                 .fn    = run_nttrans_fsctl,
12264         },
12265         {
12266                 .name  = "CLI_ECHO",
12267                 .fn    = run_cli_echo,
12268         },
12269         {
12270                 .name  = "CLI_SPLICE",
12271                 .fn    = run_cli_splice,
12272         },
12273         {
12274                 .name  = "TLDAP",
12275                 .fn    = run_tldap,
12276         },
12277         {
12278                 .name  = "STREAMERROR",
12279                 .fn    = run_streamerror,
12280         },
12281         {
12282                 .name  = "NOTIFY-BENCH",
12283                 .fn    = run_notify_bench,
12284         },
12285         {
12286                 .name  = "NOTIFY-BENCH2",
12287                 .fn    = run_notify_bench2,
12288         },
12289         {
12290                 .name  = "NOTIFY-BENCH3",
12291                 .fn    = run_notify_bench3,
12292         },
12293         {
12294                 .name  = "BAD-NBT-SESSION",
12295                 .fn    = run_bad_nbt_session,
12296         },
12297         {
12298                 .name  = "IGN-BAD-NEGPROT",
12299                 .fn    = run_ign_bad_negprot,
12300         },
12301         {
12302                 .name  = "SMB-ANY-CONNECT",
12303                 .fn    = run_smb_any_connect,
12304         },
12305         {
12306                 .name  = "NOTIFY-ONLINE",
12307                 .fn    = run_notify_online,
12308         },
12309         {
12310                 .name  = "SMB2-BASIC",
12311                 .fn    = run_smb2_basic,
12312         },
12313         {
12314                 .name  = "SMB2-NEGPROT",
12315                 .fn    = run_smb2_negprot,
12316         },
12317         {
12318                 .name  = "SMB2-ANONYMOUS",
12319                 .fn    = run_smb2_anonymous,
12320         },
12321         {
12322                 .name  = "SMB2-SESSION-RECONNECT",
12323                 .fn    = run_smb2_session_reconnect,
12324         },
12325         {
12326                 .name  = "SMB2-TCON-DEPENDENCE",
12327                 .fn    = run_smb2_tcon_dependence,
12328         },
12329         {
12330                 .name  = "SMB2-MULTI-CHANNEL",
12331                 .fn    = run_smb2_multi_channel,
12332         },
12333         {
12334                 .name  = "SMB2-SESSION-REAUTH",
12335                 .fn    = run_smb2_session_reauth,
12336         },
12337         {
12338                 .name  = "SMB2-FTRUNCATE",
12339                 .fn    = run_smb2_ftruncate,
12340         },
12341         {
12342                 .name  = "SMB2-DIR-FSYNC",
12343                 .fn    = run_smb2_dir_fsync,
12344         },
12345         {
12346                 .name  = "CLEANUP1",
12347                 .fn    = run_cleanup1,
12348         },
12349         {
12350                 .name  = "CLEANUP2",
12351                 .fn    = run_cleanup2,
12352         },
12353         {
12354                 .name  = "CLEANUP3",
12355                 .fn    = run_cleanup3,
12356         },
12357         {
12358                 .name  = "CLEANUP4",
12359                 .fn    = run_cleanup4,
12360         },
12361         {
12362                 .name  = "OPLOCK-CANCEL",
12363                 .fn    = run_oplock_cancel,
12364         },
12365         {
12366                 .name  = "PIDHIGH",
12367                 .fn    = run_pidhigh,
12368         },
12369         {
12370                 .name  = "LOCAL-SUBSTITUTE",
12371                 .fn    = run_local_substitute,
12372         },
12373         {
12374                 .name  = "LOCAL-GENCACHE",
12375                 .fn    = run_local_gencache,
12376         },
12377         {
12378                 .name  = "LOCAL-DBWRAP-WATCH1",
12379                 .fn    = run_dbwrap_watch1,
12380         },
12381         {
12382                 .name  = "LOCAL-DBWRAP-WATCH2",
12383                 .fn    = run_dbwrap_watch2,
12384         },
12385         {
12386                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
12387                 .fn    = run_dbwrap_do_locked1,
12388         },
12389         {
12390                 .name  = "LOCAL-MESSAGING-READ1",
12391                 .fn    = run_messaging_read1,
12392         },
12393         {
12394                 .name  = "LOCAL-MESSAGING-READ2",
12395                 .fn    = run_messaging_read2,
12396         },
12397         {
12398                 .name  = "LOCAL-MESSAGING-READ3",
12399                 .fn    = run_messaging_read3,
12400         },
12401         {
12402                 .name  = "LOCAL-MESSAGING-READ4",
12403                 .fn    = run_messaging_read4,
12404         },
12405         {
12406                 .name  = "LOCAL-MESSAGING-FDPASS1",
12407                 .fn    = run_messaging_fdpass1,
12408         },
12409         {
12410                 .name  = "LOCAL-MESSAGING-FDPASS2",
12411                 .fn    = run_messaging_fdpass2,
12412         },
12413         {
12414                 .name  = "LOCAL-MESSAGING-FDPASS2a",
12415                 .fn    = run_messaging_fdpass2a,
12416         },
12417         {
12418                 .name  = "LOCAL-MESSAGING-FDPASS2b",
12419                 .fn    = run_messaging_fdpass2b,
12420         },
12421         {
12422                 .name  = "LOCAL-MESSAGING-SEND-ALL",
12423                 .fn    = run_messaging_send_all,
12424         },
12425         {
12426                 .name  = "LOCAL-BASE64",
12427                 .fn    = run_local_base64,
12428         },
12429         {
12430                 .name  = "LOCAL-RBTREE",
12431                 .fn    = run_local_rbtree,
12432         },
12433         {
12434                 .name  = "LOCAL-MEMCACHE",
12435                 .fn    = run_local_memcache,
12436         },
12437         {
12438                 .name  = "LOCAL-STREAM-NAME",
12439                 .fn    = run_local_stream_name,
12440         },
12441         {
12442                 .name  = "WBCLIENT-MULTI-PING",
12443                 .fn    = run_wbclient_multi_ping,
12444         },
12445         {
12446                 .name  = "LOCAL-string_to_sid",
12447                 .fn    = run_local_string_to_sid,
12448         },
12449         {
12450                 .name  = "LOCAL-sid_to_string",
12451                 .fn    = run_local_sid_to_string,
12452         },
12453         {
12454                 .name  = "LOCAL-binary_to_sid",
12455                 .fn    = run_local_binary_to_sid,
12456         },
12457         {
12458                 .name  = "LOCAL-DBTRANS",
12459                 .fn    = run_local_dbtrans,
12460         },
12461         {
12462                 .name  = "LOCAL-TEVENT-POLL",
12463                 .fn    = run_local_tevent_poll,
12464         },
12465         {
12466                 .name  = "LOCAL-CONVERT-STRING",
12467                 .fn    = run_local_convert_string,
12468         },
12469         {
12470                 .name  = "LOCAL-CONV-AUTH-INFO",
12471                 .fn    = run_local_conv_auth_info,
12472         },
12473         {
12474                 .name  = "LOCAL-hex_encode_buf",
12475                 .fn    = run_local_hex_encode_buf,
12476         },
12477         {
12478                 .name  = "LOCAL-IDMAP-TDB-COMMON",
12479                 .fn    = run_idmap_tdb_common_test,
12480         },
12481         {
12482                 .name  = "LOCAL-remove_duplicate_addrs2",
12483                 .fn    = run_local_remove_duplicate_addrs2,
12484         },
12485         {
12486                 .name  = "local-tdb-opener",
12487                 .fn    = run_local_tdb_opener,
12488         },
12489         {
12490                 .name  = "local-tdb-writer",
12491                 .fn    = run_local_tdb_writer,
12492         },
12493         {
12494                 .name  = "LOCAL-DBWRAP-CTDB",
12495                 .fn    = run_local_dbwrap_ctdb,
12496         },
12497         {
12498                 .name  = "LOCAL-BENCH-PTHREADPOOL",
12499                 .fn    = run_bench_pthreadpool,
12500         },
12501         {
12502                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
12503                 .fn    = run_pthreadpool_tevent,
12504         },
12505         {
12506                 .name  = "LOCAL-G-LOCK1",
12507                 .fn    = run_g_lock1,
12508         },
12509         {
12510                 .name  = "LOCAL-G-LOCK2",
12511                 .fn    = run_g_lock2,
12512         },
12513         {
12514                 .name  = "LOCAL-G-LOCK3",
12515                 .fn    = run_g_lock3,
12516         },
12517         {
12518                 .name  = "LOCAL-G-LOCK4",
12519                 .fn    = run_g_lock4,
12520         },
12521         {
12522                 .name  = "LOCAL-G-LOCK5",
12523                 .fn    = run_g_lock5,
12524         },
12525         {
12526                 .name  = "LOCAL-G-LOCK6",
12527                 .fn    = run_g_lock6,
12528         },
12529         {
12530                 .name  = "LOCAL-G-LOCK-PING-PONG",
12531                 .fn    = run_g_lock_ping_pong,
12532         },
12533         {
12534                 .name  = "LOCAL-CANONICALIZE-PATH",
12535                 .fn    = run_local_canonicalize_path,
12536         },
12537         {
12538                 .name  = "LOCAL-NAMEMAP-CACHE1",
12539                 .fn    = run_local_namemap_cache1,
12540         },
12541         {
12542                 .name  = "LOCAL-IDMAP-CACHE1",
12543                 .fn    = run_local_idmap_cache1,
12544         },
12545         {
12546                 .name  = "qpathinfo-bufsize",
12547                 .fn    = run_qpathinfo_bufsize,
12548         },
12549         {
12550                 .name  = "hide-new-files-timeout",
12551                 .fn    = run_hidenewfiles,
12552         },
12553         {
12554                 .name = NULL,
12555         },
12556 };
12557
12558 /****************************************************************************
12559 run a specified test or "ALL"
12560 ****************************************************************************/
12561 static bool run_test(const char *name)
12562 {
12563         bool ret = True;
12564         bool result = True;
12565         bool found = False;
12566         int i;
12567         double t;
12568         if (strequal(name,"ALL")) {
12569                 for (i=0;torture_ops[i].name;i++) {
12570                         run_test(torture_ops[i].name);
12571                 }
12572                 found = True;
12573         }
12574
12575         for (i=0;torture_ops[i].name;i++) {
12576                 fstr_sprintf(randomfname, "\\XX%x", 
12577                          (unsigned)random());
12578
12579                 if (strequal(name, torture_ops[i].name)) {
12580                         found = True;
12581                         printf("Running %s\n", name);
12582                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
12583                                 t = create_procs(torture_ops[i].fn, &result);
12584                                 if (!result) { 
12585                                         ret = False;
12586                                         printf("TEST %s FAILED!\n", name);
12587                                 }
12588                         } else {
12589                                 struct timeval start;
12590                                 start = timeval_current();
12591                                 if (!torture_ops[i].fn(0)) {
12592                                         ret = False;
12593                                         printf("TEST %s FAILED!\n", name);
12594                                 }
12595                                 t = timeval_elapsed(&start);
12596                         }
12597                         printf("%s took %g secs\n\n", name, t);
12598                 }
12599         }
12600
12601         if (!found) {
12602                 printf("Did not find a test named %s\n", name);
12603                 ret = False;
12604         }
12605
12606         return ret;
12607 }
12608
12609
12610 static void usage(void)
12611 {
12612         int i;
12613
12614         printf("WARNING samba4 test suite is much more complete nowadays.\n");
12615         printf("Please use samba4 torture.\n\n");
12616
12617         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
12618
12619         printf("\t-d debuglevel\n");
12620         printf("\t-U user%%pass\n");
12621         printf("\t-k                    use kerberos\n");
12622         printf("\t-N numprocs\n");
12623         printf("\t-n my_netbios_name\n");
12624         printf("\t-W workgroup\n");
12625         printf("\t-o num_operations\n");
12626         printf("\t-O socket_options\n");
12627         printf("\t-m maximum protocol\n");
12628         printf("\t-L use oplocks\n");
12629         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
12630         printf("\t-A showall\n");
12631         printf("\t-p port\n");
12632         printf("\t-s seed\n");
12633         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
12634         printf("\t-f filename           filename to test\n");
12635         printf("\t-e                    encrypt\n");
12636         printf("\n\n");
12637
12638         printf("tests are:");
12639         for (i=0;torture_ops[i].name;i++) {
12640                 printf(" %s", torture_ops[i].name);
12641         }
12642         printf("\n");
12643
12644         printf("default test is ALL\n");
12645
12646         exit(1);
12647 }
12648
12649 /****************************************************************************
12650   main program
12651 ****************************************************************************/
12652  int main(int argc,char *argv[])
12653 {
12654         int opt, i;
12655         char *p;
12656         int gotuser = 0;
12657         int gotpass = 0;
12658         bool correct = True;
12659         TALLOC_CTX *frame = talloc_stackframe();
12660         int seed = time(NULL);
12661
12662 #ifdef HAVE_SETBUFFER
12663         setbuffer(stdout, NULL, 0);
12664 #endif
12665
12666         setup_logging("smbtorture", DEBUG_STDOUT);
12667
12668         smb_init_locale();
12669         fault_setup();
12670
12671         if (is_default_dyn_CONFIGFILE()) {
12672                 if(getenv("SMB_CONF_PATH")) {
12673                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
12674                 }
12675         }
12676         lp_load_global(get_dyn_CONFIGFILE());
12677         load_interfaces();
12678
12679         if (argc < 2) {
12680                 usage();
12681         }
12682
12683         for(p = argv[1]; *p; p++)
12684           if(*p == '\\')
12685             *p = '/';
12686
12687         if (strncmp(argv[1], "//", 2)) {
12688                 usage();
12689         }
12690
12691         fstrcpy(host, &argv[1][2]);
12692         p = strchr_m(&host[2],'/');
12693         if (!p) {
12694                 usage();
12695         }
12696         *p = 0;
12697         fstrcpy(share, p+1);
12698
12699         fstrcpy(myname, get_myname(talloc_tos()));
12700         if (!*myname) {
12701                 fprintf(stderr, "Failed to get my hostname.\n");
12702                 return 1;
12703         }
12704
12705         if (*username == 0 && getenv("LOGNAME")) {
12706           fstrcpy(username,getenv("LOGNAME"));
12707         }
12708
12709         argc--;
12710         argv++;
12711
12712         fstrcpy(workgroup, lp_workgroup());
12713
12714         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
12715                != EOF) {
12716                 switch (opt) {
12717                 case 'p':
12718                         port_to_use = atoi(optarg);
12719                         break;
12720                 case 's':
12721                         seed = atoi(optarg);
12722                         break;
12723                 case 'W':
12724                         fstrcpy(workgroup,optarg);
12725                         break;
12726                 case 'm':
12727                         lp_set_cmdline("client max protocol", optarg);
12728                         break;
12729                 case 'N':
12730                         torture_nprocs = atoi(optarg);
12731                         break;
12732                 case 'o':
12733                         torture_numops = atoi(optarg);
12734                         break;
12735                 case 'd':
12736                         lp_set_cmdline("log level", optarg);
12737                         break;
12738                 case 'O':
12739                         sockops = optarg;
12740                         break;
12741                 case 'L':
12742                         use_oplocks = True;
12743                         break;
12744                 case 'l':
12745                         local_path = optarg;
12746                         break;
12747                 case 'A':
12748                         torture_showall = True;
12749                         break;
12750                 case 'n':
12751                         fstrcpy(myname, optarg);
12752                         break;
12753                 case 'c':
12754                         client_txt = optarg;
12755                         break;
12756                 case 'e':
12757                         do_encrypt = true;
12758                         break;
12759                 case 'k':
12760 #ifdef HAVE_KRB5
12761                         use_kerberos = True;
12762 #else
12763                         d_printf("No kerberos support compiled in\n");
12764                         exit(1);
12765 #endif
12766                         break;
12767                 case 'U':
12768                         gotuser = 1;
12769                         fstrcpy(username,optarg);
12770                         p = strchr_m(username,'%');
12771                         if (p) {
12772                                 *p = 0;
12773                                 fstrcpy(password, p+1);
12774                                 gotpass = 1;
12775                         }
12776                         break;
12777                 case 'b':
12778                         fstrcpy(multishare_conn_fname, optarg);
12779                         use_multishare_conn = True;
12780                         break;
12781                 case 'B':
12782                         torture_blocksize = atoi(optarg);
12783                         break;
12784                 case 'f':
12785                         test_filename = SMB_STRDUP(optarg);
12786                         break;
12787                 default:
12788                         printf("Unknown option %c (%d)\n", (char)opt, opt);
12789                         usage();
12790                 }
12791         }
12792
12793         d_printf("using seed %d\n", seed);
12794
12795         srandom(seed);
12796
12797         if(use_kerberos && !gotuser) gotpass = True;
12798
12799         while (!gotpass) {
12800                 char pwd[256] = {0};
12801                 int rc;
12802
12803                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
12804                 if (rc == 0) {
12805                         fstrcpy(password, pwd);
12806                         gotpass = 1;
12807                 }
12808         }
12809
12810         printf("host=%s share=%s user=%s myname=%s\n", 
12811                host, share, username, myname);
12812
12813         torture_creds = cli_session_creds_init(frame,
12814                                                username,
12815                                                workgroup,
12816                                                NULL, /* realm */
12817                                                password,
12818                                                use_kerberos,
12819                                                false, /* fallback_after_kerberos */
12820                                                false, /* use_ccache */
12821                                                false); /* password_is_nt_hash */
12822         if (torture_creds == NULL) {
12823                 d_printf("cli_session_creds_init() failed.\n");
12824                 exit(1);
12825         }
12826
12827         if (argc == optind) {
12828                 correct = run_test("ALL");
12829         } else {
12830                 for (i=optind;i<argc;i++) {
12831                         if (!run_test(argv[i])) {
12832                                 correct = False;
12833                         }
12834                 }
12835         }
12836
12837         TALLOC_FREE(frame);
12838
12839         if (correct) {
12840                 return(0);
12841         } else {
12842                 return(1);
12843         }
12844 }