Fix typos in "valid"
[sfrench/samba-autobuild/.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "../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, "
6420                        "should have failed.\n",
6421                        dname);
6422                 goto out;
6423         } else {
6424                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
6425                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
6426                         goto out;
6427                 }
6428         }
6429
6430         /* Create the file. */
6431         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
6432                                 0600, &fnum1);
6433         if (!NT_STATUS_IS_OK(status)) {
6434                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
6435                 goto out;
6436         }
6437
6438         /* Write some data into it. */
6439         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
6440                               NULL);
6441         if (!NT_STATUS_IS_OK(status)) {
6442                 printf("cli_write failed: %s\n", nt_errstr(status));
6443                 goto out;
6444         }
6445
6446         cli_close(cli1, fnum1);
6447
6448         /* Now create a hardlink. */
6449         status = cli_posix_hardlink(cli1, fname, hname);
6450         if (!NT_STATUS_IS_OK(status)) {
6451                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
6452                 goto out;
6453         }
6454
6455         /* Now create a symlink. */
6456         status = cli_posix_symlink(cli1, fname, sname);
6457         if (!NT_STATUS_IS_OK(status)) {
6458                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
6459                 goto out;
6460         }
6461
6462         /* Open the hardlink for read. */
6463         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
6464         if (!NT_STATUS_IS_OK(status)) {
6465                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
6466                 goto out;
6467         }
6468
6469         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
6470         if (!NT_STATUS_IS_OK(status)) {
6471                 printf("POSIX read of %s failed (%s)\n", hname,
6472                        nt_errstr(status));
6473                 goto out;
6474         } else if (nread != 10) {
6475                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
6476                        hname, (unsigned long)nread, 10);
6477                 goto out;
6478         }
6479
6480         if (memcmp(buf, "TEST DATA\n", 10)) {
6481                 printf("invalid data read from hardlink\n");
6482                 goto out;
6483         }
6484
6485         /* Do a POSIX lock/unlock. */
6486         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
6487         if (!NT_STATUS_IS_OK(status)) {
6488                 printf("POSIX lock failed %s\n", nt_errstr(status));
6489                 goto out;
6490         }
6491
6492         /* Punch a hole in the locked area. */
6493         status = cli_posix_unlock(cli1, fnum1, 10, 80);
6494         if (!NT_STATUS_IS_OK(status)) {
6495                 printf("POSIX unlock failed %s\n", nt_errstr(status));
6496                 goto out;
6497         }
6498
6499         cli_close(cli1, fnum1);
6500
6501         /* Open the symlink for read - this should fail. A POSIX
6502            client should not be doing opens on a symlink. */
6503         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
6504         if (NT_STATUS_IS_OK(status)) {
6505                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
6506                 goto out;
6507         } else {
6508                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
6509                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
6510                         printf("POSIX open of %s should have failed "
6511                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
6512                                 "failed with %s instead.\n",
6513                                 sname, nt_errstr(status));
6514                         goto out;
6515                 }
6516         }
6517
6518         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
6519         if (!NT_STATUS_IS_OK(status)) {
6520                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
6521                 goto out;
6522         }
6523
6524         if (strcmp(namebuf, fname) != 0) {
6525                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
6526                         sname, fname, namebuf);
6527                 goto out;
6528         }
6529
6530         status = cli_posix_rmdir(cli1, dname);
6531         if (!NT_STATUS_IS_OK(status)) {
6532                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
6533                 goto out;
6534         }
6535
6536         /* Check directory opens with a specific permission. */
6537         status = cli_posix_mkdir(cli1, dname, 0700);
6538         if (!NT_STATUS_IS_OK(status)) {
6539                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
6540                 goto out;
6541         }
6542
6543         /* Ensure st_mode == 0700 */
6544         status = cli_posix_stat(cli1, dname, &sbuf);
6545         if (!NT_STATUS_IS_OK(status)) {
6546                 printf("stat failed (%s)\n", nt_errstr(status));
6547                 goto out;
6548         }
6549
6550         if ((sbuf.st_ex_mode & 07777) != 0700) {
6551                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
6552                                 (unsigned int)(sbuf.st_ex_mode & 07777));
6553                 goto out;
6554         }
6555
6556         /*
6557          * Now create a Windows file, and attempt a POSIX unlink.
6558          * This should fail with a sharing violation but due to:
6559          *
6560          * [Bug 9571] Unlink after open causes smbd to panic
6561          *
6562          * ensure we've fixed the lock ordering violation.
6563          */
6564
6565         status = cli_ntcreate(cli1, fname_windows, 0,
6566                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
6567                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6568                         FILE_CREATE,
6569                         0x0, 0x0, &fnum2, NULL);
6570         if (!NT_STATUS_IS_OK(status)) {
6571                 printf("Windows create of %s failed (%s)\n", fname_windows,
6572                         nt_errstr(status));
6573                 goto out;
6574         }
6575
6576         /* Now try posix_unlink. */
6577         status = cli_posix_unlink(cli1, fname_windows);
6578         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6579                 printf("POSIX unlink of %s should fail "
6580                         "with NT_STATUS_SHARING_VIOLATION "
6581                         "got %s instead !\n",
6582                         fname_windows,
6583                         nt_errstr(status));
6584                 goto out;
6585         }
6586
6587         cli_close(cli1, fnum2);
6588
6589         printf("Simple POSIX open test passed\n");
6590         correct = true;
6591
6592   out:
6593
6594         if (fnum1 != (uint16_t)-1) {
6595                 cli_close(cli1, fnum1);
6596                 fnum1 = (uint16_t)-1;
6597         }
6598
6599         if (fnum2 != (uint16_t)-1) {
6600                 cli_close(cli1, fnum2);
6601                 fnum2 = (uint16_t)-1;
6602         }
6603
6604         cli_setatr(cli1, sname, 0, 0);
6605         cli_posix_unlink(cli1, sname);
6606         cli_setatr(cli1, hname, 0, 0);
6607         cli_posix_unlink(cli1, hname);
6608         cli_setatr(cli1, fname, 0, 0);
6609         cli_posix_unlink(cli1, fname);
6610         cli_setatr(cli1, dname, 0, 0);
6611         cli_posix_rmdir(cli1, dname);
6612         cli_setatr(cli1, fname_windows, 0, 0);
6613         cli_posix_unlink(cli1, fname_windows);
6614
6615         if (!torture_close_connection(cli1)) {
6616                 correct = false;
6617         }
6618
6619         return correct;
6620 }
6621
6622 /*
6623   Test POSIX and Windows ACLs are rejected on symlinks.
6624  */
6625 static bool run_acl_symlink_test(int dummy)
6626 {
6627         static struct cli_state *cli;
6628         const char *fname = "posix_file";
6629         const char *sname = "posix_symlink";
6630         uint16_t fnum = (uint16_t)-1;
6631         bool correct = false;
6632         NTSTATUS status;
6633         char *posix_acl = NULL;
6634         size_t posix_acl_len = 0;
6635         char *posix_acl_sym = NULL;
6636         size_t posix_acl_len_sym = 0;
6637         struct security_descriptor *sd = NULL;
6638         struct security_descriptor *sd_sym = NULL;
6639         TALLOC_CTX *frame = NULL;
6640
6641         frame = talloc_stackframe();
6642
6643         printf("Starting acl symlink test\n");
6644
6645         if (!torture_open_connection(&cli, 0)) {
6646                 TALLOC_FREE(frame);
6647                 return false;
6648         }
6649
6650         smbXcli_conn_set_sockopt(cli->conn, sockops);
6651
6652         status = torture_setup_unix_extensions(cli);
6653         if (!NT_STATUS_IS_OK(status)) {
6654                 TALLOC_FREE(frame);
6655                 return false;
6656         }
6657
6658         cli_setatr(cli, fname, 0, 0);
6659         cli_posix_unlink(cli, fname);
6660         cli_setatr(cli, sname, 0, 0);
6661         cli_posix_unlink(cli, sname);
6662
6663         status = cli_ntcreate(cli,
6664                         fname,
6665                         0,
6666                         READ_CONTROL_ACCESS,
6667                         0,
6668                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6669                         FILE_CREATE,
6670                         0x0,
6671                         0x0,
6672                         &fnum,
6673                         NULL);
6674
6675         if (!NT_STATUS_IS_OK(status)) {
6676                 printf("cli_ntcreate of %s failed (%s)\n",
6677                         fname,
6678                         nt_errstr(status));
6679                 goto out;
6680         }
6681
6682         /* Get the Windows ACL on the file. */
6683         status = cli_query_secdesc(cli,
6684                                 fnum,
6685                                 frame,
6686                                 &sd);
6687         if (!NT_STATUS_IS_OK(status)) {
6688                 printf("cli_query_secdesc failed (%s)\n",
6689                         nt_errstr(status));
6690                 goto out;
6691         }
6692
6693         /* Get the POSIX ACL on the file. */
6694         status = cli_posix_getacl(cli,
6695                                 fname,
6696                                 frame,
6697                                 &posix_acl_len,
6698                                 &posix_acl);
6699
6700         if (!NT_STATUS_IS_OK(status)) {
6701                 printf("cli_posix_getacl failed (%s)\n",
6702                         nt_errstr(status));
6703                 goto out;
6704         }
6705
6706         status = cli_close(cli, fnum);
6707         if (!NT_STATUS_IS_OK(status)) {
6708                 printf("close failed (%s)\n", nt_errstr(status));
6709                 goto out;
6710         }
6711         fnum = (uint16_t)-1;
6712
6713         /* Now create a symlink. */
6714         status = cli_posix_symlink(cli, fname, sname);
6715         if (!NT_STATUS_IS_OK(status)) {
6716                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
6717                         sname,
6718                         fname,
6719                         nt_errstr(status));
6720                 goto out;
6721         }
6722
6723         /* Open a handle on the symlink. */
6724         status = cli_ntcreate(cli,
6725                         sname,
6726                         0,
6727                         READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
6728                         0,
6729                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6730                         FILE_OPEN,
6731                         0x0,
6732                         0x0,
6733                         &fnum,
6734                         NULL);
6735
6736         if (!NT_STATUS_IS_OK(status)) {
6737                 printf("cli_posix_open of %s failed (%s)\n",
6738                         sname,
6739                         nt_errstr(status));
6740                 goto out;
6741         }
6742
6743         /* Get the Windows ACL on the symlink handle. Should fail */
6744         status = cli_query_secdesc(cli,
6745                                 fnum,
6746                                 frame,
6747                                 &sd_sym);
6748
6749         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6750                 printf("cli_query_secdesc on a symlink gave %s. "
6751                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6752                         nt_errstr(status));
6753                 goto out;
6754         }
6755
6756         /* Get the POSIX ACL on the symlink pathname. Should fail. */
6757         status = cli_posix_getacl(cli,
6758                                 sname,
6759                                 frame,
6760                                 &posix_acl_len_sym,
6761                                 &posix_acl_sym);
6762
6763         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6764                 printf("cli_posix_getacl on a symlink gave %s. "
6765                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6766                         nt_errstr(status));
6767                 goto out;
6768         }
6769
6770         /* Set the Windows ACL on the symlink handle. Should fail */
6771         status = cli_set_security_descriptor(cli,
6772                                 fnum,
6773                                 SECINFO_DACL,
6774                                 sd);
6775
6776         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6777                 printf("cli_query_secdesc on a symlink gave %s. "
6778                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6779                         nt_errstr(status));
6780                 goto out;
6781         }
6782
6783         /* Set the POSIX ACL on the symlink pathname. Should fail. */
6784         status = cli_posix_setacl(cli,
6785                                 sname,
6786                                 posix_acl,
6787                                 posix_acl_len);
6788
6789         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6790                 printf("cli_posix_getacl on a symlink gave %s. "
6791                         "Should be NT_STATUS_ACCESS_DENIED.\n",
6792                         nt_errstr(status));
6793                 goto out;
6794         }
6795
6796         printf("ACL symlink test passed\n");
6797         correct = true;
6798
6799   out:
6800
6801         if (fnum != (uint16_t)-1) {
6802                 cli_close(cli, fnum);
6803                 fnum = (uint16_t)-1;
6804         }
6805
6806         cli_setatr(cli, sname, 0, 0);
6807         cli_posix_unlink(cli, sname);
6808         cli_setatr(cli, fname, 0, 0);
6809         cli_posix_unlink(cli, fname);
6810
6811         if (!torture_close_connection(cli)) {
6812                 correct = false;
6813         }
6814
6815         TALLOC_FREE(frame);
6816         return correct;
6817 }
6818
6819 /*
6820   Test POSIX can delete a file containing streams.
6821  */
6822 static bool run_posix_stream_delete(int dummy)
6823 {
6824         struct cli_state *cli1 = NULL;
6825         struct cli_state *cli2 = NULL;
6826         const char *fname = "streamfile";
6827         const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
6828         uint16_t fnum1 = (uint16_t)-1;
6829         bool correct = false;
6830         NTSTATUS status;
6831         TALLOC_CTX *frame = NULL;
6832
6833         frame = talloc_stackframe();
6834
6835         printf("Starting POSIX stream delete test\n");
6836
6837         if (!torture_open_connection(&cli1, 0) ||
6838                         !torture_open_connection(&cli2, 1)) {
6839                 TALLOC_FREE(frame);
6840                 return false;
6841         }
6842
6843         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6844         smbXcli_conn_set_sockopt(cli2->conn, sockops);
6845
6846         status = torture_setup_unix_extensions(cli2);
6847         if (!NT_STATUS_IS_OK(status)) {
6848                 goto out;
6849         }
6850
6851         cli_setatr(cli1, fname, 0, 0);
6852         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6853
6854         /* Create the file. */
6855         status = cli_ntcreate(cli1,
6856                         fname,
6857                         0,
6858                         READ_CONTROL_ACCESS,
6859                         0,
6860                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6861                         FILE_CREATE,
6862                         0x0,
6863                         0x0,
6864                         &fnum1,
6865                         NULL);
6866
6867         if (!NT_STATUS_IS_OK(status)) {
6868                 printf("cli_ntcreate of %s failed (%s)\n",
6869                         fname,
6870                         nt_errstr(status));
6871                 goto out;
6872         }
6873
6874         status = cli_close(cli1, fnum1);
6875         if (!NT_STATUS_IS_OK(status)) {
6876                 printf("cli_close of %s failed (%s)\n",
6877                         fname,
6878                         nt_errstr(status));
6879                 goto out;
6880         }
6881         fnum1 = (uint16_t)-1;
6882
6883         /* Now create the stream. */
6884         status = cli_ntcreate(cli1,
6885                         stream_fname,
6886                         0,
6887                         FILE_WRITE_DATA,
6888                         0,
6889                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6890                         FILE_CREATE,
6891                         0x0,
6892                         0x0,
6893                         &fnum1,
6894                         NULL);
6895
6896         if (!NT_STATUS_IS_OK(status)) {
6897                 printf("cli_ntcreate of %s failed (%s)\n",
6898                         stream_fname,
6899                         nt_errstr(status));
6900                 goto out;
6901         }
6902
6903         /* Leave the stream handle open... */
6904
6905         /* POSIX unlink should fail. */
6906         status = cli_posix_unlink(cli2, fname);
6907         if (NT_STATUS_IS_OK(status)) {
6908                 printf("cli_posix_unlink of %s succeeded, should have failed\n",
6909                         fname);
6910                 goto out;
6911         }
6912
6913         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6914                 printf("cli_posix_unlink of %s failed with (%s) "
6915                         "should have been NT_STATUS_SHARING_VIOLATION\n",
6916                         fname,
6917                         nt_errstr(status));
6918                 goto out;
6919         }
6920
6921         /* Close the stream handle. */
6922         status = cli_close(cli1, fnum1);
6923         if (!NT_STATUS_IS_OK(status)) {
6924                 printf("cli_close of %s failed (%s)\n",
6925                         stream_fname,
6926                         nt_errstr(status));
6927                 goto out;
6928         }
6929         fnum1 = (uint16_t)-1;
6930
6931         /* POSIX unlink after stream handle closed should succeed. */
6932         status = cli_posix_unlink(cli2, fname);
6933         if (!NT_STATUS_IS_OK(status)) {
6934                 printf("cli_posix_unlink of %s failed (%s)\n",
6935                         fname,
6936                         nt_errstr(status));
6937                 goto out;
6938         }
6939
6940         printf("POSIX stream delete test passed\n");
6941         correct = true;
6942
6943   out:
6944
6945         if (fnum1 != (uint16_t)-1) {
6946                 cli_close(cli1, fnum1);
6947                 fnum1 = (uint16_t)-1;
6948         }
6949
6950         cli_setatr(cli1, fname, 0, 0);
6951         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6952
6953         if (!torture_close_connection(cli1)) {
6954                 correct = false;
6955         }
6956         if (!torture_close_connection(cli2)) {
6957                 correct = false;
6958         }
6959
6960         TALLOC_FREE(frame);
6961         return correct;
6962 }
6963
6964 /*
6965   Test setting EA's are rejected on symlinks.
6966  */
6967 static bool run_ea_symlink_test(int dummy)
6968 {
6969         static struct cli_state *cli;
6970         const char *fname = "posix_file_ea";
6971         const char *sname = "posix_symlink_ea";
6972         const char *ea_name = "testea_name";
6973         const char *ea_value = "testea_value";
6974         uint16_t fnum = (uint16_t)-1;
6975         bool correct = false;
6976         NTSTATUS status;
6977         size_t i, num_eas;
6978         struct ea_struct *eas = NULL;
6979         TALLOC_CTX *frame = NULL;
6980
6981         frame = talloc_stackframe();
6982
6983         printf("Starting EA symlink test\n");
6984
6985         if (!torture_open_connection(&cli, 0)) {
6986                 TALLOC_FREE(frame);
6987                 return false;
6988         }
6989
6990         smbXcli_conn_set_sockopt(cli->conn, sockops);
6991
6992         status = torture_setup_unix_extensions(cli);
6993         if (!NT_STATUS_IS_OK(status)) {
6994                 TALLOC_FREE(frame);
6995                 return false;
6996         }
6997
6998         cli_setatr(cli, fname, 0, 0);
6999         cli_posix_unlink(cli, fname);
7000         cli_setatr(cli, sname, 0, 0);
7001         cli_posix_unlink(cli, sname);
7002
7003         status = cli_ntcreate(cli,
7004                         fname,
7005                         0,
7006                         READ_CONTROL_ACCESS,
7007                         0,
7008                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7009                         FILE_CREATE,
7010                         0x0,
7011                         0x0,
7012                         &fnum,
7013                         NULL);
7014
7015         if (!NT_STATUS_IS_OK(status)) {
7016                 printf("cli_ntcreate of %s failed (%s)\n",
7017                         fname,
7018                         nt_errstr(status));
7019                 goto out;
7020         }
7021
7022         status = cli_close(cli, fnum);
7023         if (!NT_STATUS_IS_OK(status)) {
7024                 printf("close failed (%s)\n",
7025                         nt_errstr(status));
7026                 goto out;
7027         }
7028         fnum = (uint16_t)-1;
7029
7030         /* Set an EA on the path. */
7031         status = cli_set_ea_path(cli,
7032                                 fname,
7033                                 ea_name,
7034                                 ea_value,
7035                                 strlen(ea_value)+1);
7036
7037         if (!NT_STATUS_IS_OK(status)) {
7038                 printf("cli_set_ea_path failed (%s)\n",
7039                         nt_errstr(status));
7040                 goto out;
7041         }
7042
7043         /* Now create a symlink. */
7044         status = cli_posix_symlink(cli, fname, sname);
7045         if (!NT_STATUS_IS_OK(status)) {
7046                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
7047                         sname,
7048                         fname,
7049                         nt_errstr(status));
7050                 goto out;
7051         }
7052
7053         /* Get the EA list on the path. Should return value set. */
7054         status = cli_get_ea_list_path(cli,
7055                                 fname,
7056                                 frame,
7057                                 &num_eas,
7058                                 &eas);
7059
7060         if (!NT_STATUS_IS_OK(status)) {
7061                 printf("cli_get_ea_list_path failed (%s)\n",
7062                         nt_errstr(status));
7063                 goto out;
7064         }
7065
7066         /* Ensure the EA we set is there. */
7067         for (i=0; i<num_eas; i++) {
7068                 if (strcmp(eas[i].name, ea_name) == 0 &&
7069                                 eas[i].value.length == strlen(ea_value)+1 &&
7070                                 memcmp(eas[i].value.data,
7071                                         ea_value,
7072                                         eas[i].value.length) == 0) {
7073                         break;
7074                 }
7075         }
7076
7077         if (i == num_eas) {
7078                 printf("Didn't find EA on pathname %s\n",
7079                         fname);
7080                 goto out;
7081         }
7082
7083         num_eas = 0;
7084         TALLOC_FREE(eas);
7085
7086         /* Get the EA list on the symlink. Should return empty list. */
7087         status = cli_get_ea_list_path(cli,
7088                                 sname,
7089                                 frame,
7090                                 &num_eas,
7091                                 &eas);
7092
7093         if (!NT_STATUS_IS_OK(status)) {
7094                 printf("cli_get_ea_list_path failed (%s)\n",
7095                         nt_errstr(status));
7096                 goto out;
7097         }
7098
7099         if (num_eas != 0) {
7100                 printf("cli_get_ea_list_path failed (%s)\n",
7101                         nt_errstr(status));
7102                 goto out;
7103         }
7104
7105         /* Set an EA on the symlink. Should fail. */
7106         status = cli_set_ea_path(cli,
7107                                 sname,
7108                                 ea_name,
7109                                 ea_value,
7110                                 strlen(ea_value)+1);
7111
7112         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7113                 printf("cli_set_ea_path on a symlink gave %s. "
7114                         "Should be NT_STATUS_ACCESS_DENIED.\n",
7115                         nt_errstr(status));
7116                 goto out;
7117         }
7118
7119         printf("EA symlink test passed\n");
7120         correct = true;
7121
7122   out:
7123
7124         if (fnum != (uint16_t)-1) {
7125                 cli_close(cli, fnum);
7126                 fnum = (uint16_t)-1;
7127         }
7128
7129         cli_setatr(cli, sname, 0, 0);
7130         cli_posix_unlink(cli, sname);
7131         cli_setatr(cli, fname, 0, 0);
7132         cli_posix_unlink(cli, fname);
7133
7134         if (!torture_close_connection(cli)) {
7135                 correct = false;
7136         }
7137
7138         TALLOC_FREE(frame);
7139         return correct;
7140 }
7141
7142 /*
7143   Test POSIX locks are OFD-locks.
7144  */
7145 static bool run_posix_ofd_lock_test(int dummy)
7146 {
7147         static struct cli_state *cli;
7148         const char *fname = "posix_file";
7149         uint16_t fnum1 = (uint16_t)-1;
7150         uint16_t fnum2 = (uint16_t)-1;
7151         bool correct = false;
7152         NTSTATUS status;
7153         TALLOC_CTX *frame = NULL;
7154
7155         frame = talloc_stackframe();
7156
7157         printf("Starting POSIX ofd-lock test\n");
7158
7159         if (!torture_open_connection(&cli, 0)) {
7160                 TALLOC_FREE(frame);
7161                 return false;
7162         }
7163
7164         smbXcli_conn_set_sockopt(cli->conn, sockops);
7165
7166         status = torture_setup_unix_extensions(cli);
7167         if (!NT_STATUS_IS_OK(status)) {
7168                 TALLOC_FREE(frame);
7169                 return false;
7170         }
7171
7172         cli_setatr(cli, fname, 0, 0);
7173         cli_posix_unlink(cli, fname);
7174
7175         /* Open the file twice. */
7176         status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
7177                                 0600, &fnum1);
7178         if (!NT_STATUS_IS_OK(status)) {
7179                 printf("First POSIX open of %s failed\n", fname);
7180                 goto out;
7181         }
7182
7183         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
7184         if (!NT_STATUS_IS_OK(status)) {
7185                 printf("First POSIX open of %s failed\n", fname);
7186                 goto out;
7187         }
7188
7189         /* Set a 0-50 lock on fnum1. */
7190         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7191         if (!NT_STATUS_IS_OK(status)) {
7192                 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
7193                 goto out;
7194         }
7195
7196         /* Set a 60-100 lock on fnum2. */
7197         status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
7198         if (!NT_STATUS_IS_OK(status)) {
7199                 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
7200                 goto out;
7201         }
7202
7203         /* close fnum1 - 0-50 lock should go away. */
7204         status = cli_close(cli, fnum1);
7205         if (!NT_STATUS_IS_OK(status)) {
7206                 printf("close failed (%s)\n",
7207                         nt_errstr(status));
7208                 goto out;
7209         }
7210         fnum1 = (uint16_t)-1;
7211
7212         /* Change the lock context. */
7213         cli_setpid(cli, cli_getpid(cli) + 1);
7214
7215         /* Re-open fnum1. */
7216         status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
7217         if (!NT_STATUS_IS_OK(status)) {
7218                 printf("Third POSIX open of %s failed\n", fname);
7219                 goto out;
7220         }
7221
7222         /* 60-100 lock should still be there. */
7223         status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
7224         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
7225                 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
7226                 goto out;
7227         }
7228
7229         /* 0-50 lock should be gone. */
7230         status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
7231         if (!NT_STATUS_IS_OK(status)) {
7232                 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
7233                 goto out;
7234         }
7235
7236         printf("POSIX OFD lock test passed\n");
7237         correct = true;
7238
7239   out:
7240
7241         if (fnum1 != (uint16_t)-1) {
7242                 cli_close(cli, fnum1);
7243                 fnum1 = (uint16_t)-1;
7244         }
7245         if (fnum2 != (uint16_t)-1) {
7246                 cli_close(cli, fnum2);
7247                 fnum2 = (uint16_t)-1;
7248         }
7249
7250         cli_setatr(cli, fname, 0, 0);
7251         cli_posix_unlink(cli, fname);
7252
7253         if (!torture_close_connection(cli)) {
7254                 correct = false;
7255         }
7256
7257         TALLOC_FREE(frame);
7258         return correct;
7259 }
7260
7261 /*
7262   Test POSIX mkdir is case-sensitive.
7263  */
7264 static bool run_posix_mkdir_test(int dummy)
7265 {
7266         static struct cli_state *cli;
7267         const char *fname_foo = "POSIX_foo";
7268         const char *fname_foo_Foo = "POSIX_foo/Foo";
7269         const char *fname_foo_foo = "POSIX_foo/foo";
7270         const char *fname_Foo = "POSIX_Foo";
7271         const char *fname_Foo_Foo = "POSIX_Foo/Foo";
7272         const char *fname_Foo_foo = "POSIX_Foo/foo";
7273         bool correct = false;
7274         NTSTATUS status;
7275         TALLOC_CTX *frame = NULL;
7276         uint16_t fnum = (uint16_t)-1;
7277
7278         frame = talloc_stackframe();
7279
7280         printf("Starting POSIX mkdir test\n");
7281
7282         if (!torture_open_connection(&cli, 0)) {
7283                 TALLOC_FREE(frame);
7284                 return false;
7285         }
7286
7287         smbXcli_conn_set_sockopt(cli->conn, sockops);
7288
7289         status = torture_setup_unix_extensions(cli);
7290         if (!NT_STATUS_IS_OK(status)) {
7291                 TALLOC_FREE(frame);
7292                 return false;
7293         }
7294
7295         cli_posix_rmdir(cli, fname_foo_foo);
7296         cli_posix_rmdir(cli, fname_foo_Foo);
7297         cli_posix_rmdir(cli, fname_foo);
7298
7299         cli_posix_rmdir(cli, fname_Foo_foo);
7300         cli_posix_rmdir(cli, fname_Foo_Foo);
7301         cli_posix_rmdir(cli, fname_Foo);
7302
7303         /*
7304          * Create a file POSIX_foo then try
7305          * and use it in a directory path by
7306          * doing mkdir POSIX_foo/bar.
7307          * The mkdir should fail with
7308          * NT_STATUS_OBJECT_PATH_NOT_FOUND
7309          */
7310
7311         status = cli_posix_open(cli,
7312                         fname_foo,
7313                         O_RDWR|O_CREAT,
7314                         0666,
7315                         &fnum);
7316         if (!NT_STATUS_IS_OK(status)) {
7317                 printf("cli_posix_open of %s failed error %s\n",
7318                         fname_foo,
7319                         nt_errstr(status));
7320                 goto out;
7321         }
7322
7323         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
7324         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7325                 printf("cli_posix_mkdir of %s should fail with "
7326                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7327                         "%s instead\n",
7328                         fname_foo_foo,
7329                         nt_errstr(status));
7330                 goto out;
7331         }
7332
7333         status = cli_close(cli, fnum);
7334         if (!NT_STATUS_IS_OK(status)) {
7335                 printf("cli_close failed %s\n", nt_errstr(status));
7336                 goto out;
7337         }
7338         fnum = (uint16_t)-1;
7339
7340         status = cli_posix_unlink(cli, fname_foo);
7341         if (!NT_STATUS_IS_OK(status)) {
7342                 printf("cli_posix_unlink of %s failed error %s\n",
7343                         fname_foo,
7344                         nt_errstr(status));
7345                 goto out;
7346         }
7347
7348         /*
7349          * Now we've deleted everything, posix_mkdir, posix_rmdir,
7350          * posix_open, posix_unlink, on
7351          * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
7352          * not silently create POSIX_foo/foo.
7353          */
7354
7355         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
7356         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7357                 printf("cli_posix_mkdir of %s should fail with "
7358                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7359                         "%s instead\n",
7360                         fname_foo_foo,
7361                         nt_errstr(status));
7362                 goto out;
7363         }
7364
7365         status = cli_posix_rmdir(cli, fname_foo_foo);
7366         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7367                 printf("cli_posix_rmdir of %s should fail with "
7368                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7369                         "%s instead\n",
7370                         fname_foo_foo,
7371                         nt_errstr(status));
7372                 goto out;
7373         }
7374
7375         status = cli_posix_open(cli,
7376                         fname_foo_foo,
7377                         O_RDWR|O_CREAT,
7378                         0666,
7379                         &fnum);
7380         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7381                 printf("cli_posix_open of %s should fail with "
7382                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7383                         "%s instead\n",
7384                         fname_foo_foo,
7385                         nt_errstr(status));
7386                 goto out;
7387         }
7388
7389         status = cli_posix_unlink(cli, fname_foo_foo);
7390         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7391                 printf("cli_posix_unlink of %s should fail with "
7392                         "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
7393                         "%s instead\n",
7394                         fname_foo_foo,
7395                         nt_errstr(status));
7396                 goto out;
7397         }
7398
7399         status = cli_posix_mkdir(cli, fname_foo, 0777);
7400         if (!NT_STATUS_IS_OK(status)) {
7401                 printf("cli_posix_mkdir of %s failed\n", fname_foo);
7402                 goto out;
7403         }
7404
7405         status = cli_posix_mkdir(cli, fname_Foo, 0777);
7406         if (!NT_STATUS_IS_OK(status)) {
7407                 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
7408                 goto out;
7409         }
7410
7411         status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
7412         if (!NT_STATUS_IS_OK(status)) {
7413                 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
7414                 goto out;
7415         }
7416
7417         status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
7418         if (!NT_STATUS_IS_OK(status)) {
7419                 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
7420                 goto out;
7421         }
7422
7423         status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
7424         if (!NT_STATUS_IS_OK(status)) {
7425                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
7426                 goto out;
7427         }
7428
7429         status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
7430         if (!NT_STATUS_IS_OK(status)) {
7431                 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
7432                 goto out;
7433         }
7434
7435         printf("POSIX mkdir test passed\n");
7436         correct = true;
7437
7438   out:
7439
7440         if (fnum != (uint16_t)-1) {
7441                 cli_close(cli, fnum);
7442                 fnum = (uint16_t)-1;
7443         }
7444
7445         cli_posix_rmdir(cli, fname_foo_foo);
7446         cli_posix_rmdir(cli, fname_foo_Foo);
7447         cli_posix_rmdir(cli, fname_foo);
7448
7449         cli_posix_rmdir(cli, fname_Foo_foo);
7450         cli_posix_rmdir(cli, fname_Foo_Foo);
7451         cli_posix_rmdir(cli, fname_Foo);
7452
7453         if (!torture_close_connection(cli)) {
7454                 correct = false;
7455         }
7456
7457         TALLOC_FREE(frame);
7458         return correct;
7459 }
7460
7461
7462 static uint32_t open_attrs_table[] = {
7463                 FILE_ATTRIBUTE_NORMAL,
7464                 FILE_ATTRIBUTE_ARCHIVE,
7465                 FILE_ATTRIBUTE_READONLY,
7466                 FILE_ATTRIBUTE_HIDDEN,
7467                 FILE_ATTRIBUTE_SYSTEM,
7468
7469                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
7470                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
7471                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
7472                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7473                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7474                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7475
7476                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
7477                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
7478                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
7479                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
7480 };
7481
7482 struct trunc_open_results {
7483         unsigned int num;
7484         uint32_t init_attr;
7485         uint32_t trunc_attr;
7486         uint32_t result_attr;
7487 };
7488
7489 static struct trunc_open_results attr_results[] = {
7490         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7491         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7492         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7493         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
7494         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
7495         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
7496         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7497         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7498         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7499         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7500         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7501         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
7502         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7503         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7504         { 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 },
7505         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7506         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7507         { 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 },
7508         { 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 },
7509         { 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 },
7510         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7511         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
7512         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
7513         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7514         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
7515         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
7516 };
7517
7518 static bool run_openattrtest(int dummy)
7519 {
7520         static struct cli_state *cli1;
7521         const char *fname = "\\openattr.file";
7522         uint16_t fnum1;
7523         bool correct = True;
7524         uint16_t attr;
7525         unsigned int i, j, k, l;
7526         NTSTATUS status;
7527
7528         printf("starting open attr test\n");
7529
7530         if (!torture_open_connection(&cli1, 0)) {
7531                 return False;
7532         }
7533
7534         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7535
7536         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
7537                 cli_setatr(cli1, fname, 0, 0);
7538                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7539
7540                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
7541                                        open_attrs_table[i], FILE_SHARE_NONE,
7542                                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7543                 if (!NT_STATUS_IS_OK(status)) {
7544                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7545                         return False;
7546                 }
7547
7548                 status = cli_close(cli1, fnum1);
7549                 if (!NT_STATUS_IS_OK(status)) {
7550                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
7551                         return False;
7552                 }
7553
7554                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
7555                         status = cli_ntcreate(cli1, fname, 0,
7556                                               FILE_READ_DATA|FILE_WRITE_DATA,
7557                                               open_attrs_table[j],
7558                                               FILE_SHARE_NONE, FILE_OVERWRITE,
7559                                               0, 0, &fnum1, NULL);
7560                         if (!NT_STATUS_IS_OK(status)) {
7561                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7562                                         if (attr_results[l].num == k) {
7563                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
7564                                                                 k, open_attrs_table[i],
7565                                                                 open_attrs_table[j],
7566                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
7567                                                 correct = False;
7568                                         }
7569                                 }
7570
7571                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7572                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
7573                                                         k, open_attrs_table[i], open_attrs_table[j],
7574                                                         nt_errstr(status));
7575                                         correct = False;
7576                                 }
7577 #if 0
7578                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
7579 #endif
7580                                 k++;
7581                                 continue;
7582                         }
7583
7584                         status = cli_close(cli1, fnum1);
7585                         if (!NT_STATUS_IS_OK(status)) {
7586                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
7587                                 return False;
7588                         }
7589
7590                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
7591                         if (!NT_STATUS_IS_OK(status)) {
7592                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
7593                                 return False;
7594                         }
7595
7596 #if 0
7597                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
7598                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
7599 #endif
7600
7601                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
7602                                 if (attr_results[l].num == k) {
7603                                         if (attr != attr_results[l].result_attr ||
7604                                                         open_attrs_table[i] != attr_results[l].init_attr ||
7605                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
7606                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
7607                                                 open_attrs_table[i],
7608                                                 open_attrs_table[j],
7609                                                 (unsigned int)attr,
7610                                                 attr_results[l].result_attr);
7611                                                 correct = False;
7612                                         }
7613                                         break;
7614                                 }
7615                         }
7616                         k++;
7617                 }
7618         }
7619
7620         cli_setatr(cli1, fname, 0, 0);
7621         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7622
7623         printf("open attr test %s.\n", correct ? "passed" : "failed");
7624
7625         if (!torture_close_connection(cli1)) {
7626                 correct = False;
7627         }
7628         return correct;
7629 }
7630
7631 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
7632                     const char *name, void *state)
7633 {
7634         int *matched = (int *)state;
7635         if (matched != NULL) {
7636                 *matched += 1;
7637         }
7638         return NT_STATUS_OK;
7639 }
7640
7641 /*
7642   test directory listing speed
7643  */
7644 static bool run_dirtest(int dummy)
7645 {
7646         int i;
7647         static struct cli_state *cli;
7648         uint16_t fnum;
7649         struct timeval core_start;
7650         bool correct = True;
7651         int matched;
7652
7653         printf("starting directory test\n");
7654
7655         if (!torture_open_connection(&cli, 0)) {
7656                 return False;
7657         }
7658
7659         smbXcli_conn_set_sockopt(cli->conn, sockops);
7660
7661         srandom(0);
7662         for (i=0;i<torture_numops;i++) {
7663                 fstring fname;
7664                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7665                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
7666                         fprintf(stderr,"Failed to open %s\n", fname);
7667                         return False;
7668                 }
7669                 cli_close(cli, fnum);
7670         }
7671
7672         core_start = timeval_current();
7673
7674         matched = 0;
7675         cli_list(cli, "a*.*", 0, list_fn, &matched);
7676         printf("Matched %d\n", matched);
7677
7678         matched = 0;
7679         cli_list(cli, "b*.*", 0, list_fn, &matched);
7680         printf("Matched %d\n", matched);
7681
7682         matched = 0;
7683         cli_list(cli, "xyzabc", 0, list_fn, &matched);
7684         printf("Matched %d\n", matched);
7685
7686         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
7687
7688         srandom(0);
7689         for (i=0;i<torture_numops;i++) {
7690                 fstring fname;
7691                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
7692                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7693         }
7694
7695         if (!torture_close_connection(cli)) {
7696                 correct = False;
7697         }
7698
7699         printf("finished dirtest\n");
7700
7701         return correct;
7702 }
7703
7704 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
7705                    void *state)
7706 {
7707         struct cli_state *pcli = (struct cli_state *)state;
7708         fstring fname;
7709         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
7710
7711         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7712                 return NT_STATUS_OK;
7713
7714         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7715                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
7716                         printf("del_fn: failed to rmdir %s\n,", fname );
7717         } else {
7718                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
7719                         printf("del_fn: failed to unlink %s\n,", fname );
7720         }
7721         return NT_STATUS_OK;
7722 }
7723
7724
7725 /*
7726   sees what IOCTLs are supported
7727  */
7728 bool torture_ioctl_test(int dummy)
7729 {
7730         static struct cli_state *cli;
7731         uint16_t device, function;
7732         uint16_t fnum;
7733         const char *fname = "\\ioctl.dat";
7734         DATA_BLOB blob;
7735         NTSTATUS status;
7736
7737         if (!torture_open_connection(&cli, 0)) {
7738                 return False;
7739         }
7740
7741         printf("starting ioctl test\n");
7742
7743         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7744
7745         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7746         if (!NT_STATUS_IS_OK(status)) {
7747                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7748                 return False;
7749         }
7750
7751         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
7752         printf("ioctl device info: %s\n", nt_errstr(status));
7753
7754         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
7755         printf("ioctl job info: %s\n", nt_errstr(status));
7756
7757         for (device=0;device<0x100;device++) {
7758                 printf("ioctl test with device = 0x%x\n", device);
7759                 for (function=0;function<0x100;function++) {
7760                         uint32_t code = (device<<16) | function;
7761
7762                         status = cli_raw_ioctl(cli, fnum, code, &blob);
7763
7764                         if (NT_STATUS_IS_OK(status)) {
7765                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
7766                                        (int)blob.length);
7767                                 data_blob_free(&blob);
7768                         }
7769                 }
7770         }
7771
7772         if (!torture_close_connection(cli)) {
7773                 return False;
7774         }
7775
7776         return True;
7777 }
7778
7779
7780 /*
7781   tries varients of chkpath
7782  */
7783 bool torture_chkpath_test(int dummy)
7784 {
7785         static struct cli_state *cli;
7786         uint16_t fnum;
7787         bool ret;
7788         NTSTATUS status;
7789
7790         if (!torture_open_connection(&cli, 0)) {
7791                 return False;
7792         }
7793
7794         printf("starting chkpath test\n");
7795
7796         /* cleanup from an old run */
7797         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7798         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7799         cli_rmdir(cli, "\\chkpath.dir");
7800
7801         status = cli_mkdir(cli, "\\chkpath.dir");
7802         if (!NT_STATUS_IS_OK(status)) {
7803                 printf("mkdir1 failed : %s\n", nt_errstr(status));
7804                 return False;
7805         }
7806
7807         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
7808         if (!NT_STATUS_IS_OK(status)) {
7809                 printf("mkdir2 failed : %s\n", nt_errstr(status));
7810                 return False;
7811         }
7812
7813         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
7814                           DENY_NONE, &fnum);
7815         if (!NT_STATUS_IS_OK(status)) {
7816                 printf("open1 failed (%s)\n", nt_errstr(status));
7817                 return False;
7818         }
7819         cli_close(cli, fnum);
7820
7821         status = cli_chkpath(cli, "\\chkpath.dir");
7822         if (!NT_STATUS_IS_OK(status)) {
7823                 printf("chkpath1 failed: %s\n", nt_errstr(status));
7824                 ret = False;
7825         }
7826
7827         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
7828         if (!NT_STATUS_IS_OK(status)) {
7829                 printf("chkpath2 failed: %s\n", nt_errstr(status));
7830                 ret = False;
7831         }
7832
7833         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
7834         if (!NT_STATUS_IS_OK(status)) {
7835                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7836                                   NT_STATUS_NOT_A_DIRECTORY);
7837         } else {
7838                 printf("* chkpath on a file should fail\n");
7839                 ret = False;
7840         }
7841
7842         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
7843         if (!NT_STATUS_IS_OK(status)) {
7844                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
7845                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
7846         } else {
7847                 printf("* chkpath on a non existent file should fail\n");
7848                 ret = False;
7849         }
7850
7851         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
7852         if (!NT_STATUS_IS_OK(status)) {
7853                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
7854                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
7855         } else {
7856                 printf("* chkpath on a non existent component should fail\n");
7857                 ret = False;
7858         }
7859
7860         cli_rmdir(cli, "\\chkpath.dir\\dir2");
7861         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7862         cli_rmdir(cli, "\\chkpath.dir");
7863
7864         if (!torture_close_connection(cli)) {
7865                 return False;
7866         }
7867
7868         return ret;
7869 }
7870
7871 static bool run_eatest(int dummy)
7872 {
7873         static struct cli_state *cli;
7874         const char *fname = "\\eatest.txt";
7875         bool correct = True;
7876         uint16_t fnum;
7877         int i;
7878         size_t num_eas;
7879         struct ea_struct *ea_list = NULL;
7880         TALLOC_CTX *mem_ctx = talloc_init("eatest");
7881         NTSTATUS status;
7882
7883         printf("starting eatest\n");
7884
7885         if (!torture_open_connection(&cli, 0)) {
7886                 talloc_destroy(mem_ctx);
7887                 return False;
7888         }
7889
7890         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7891
7892         status = cli_ntcreate(cli, fname, 0,
7893                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
7894                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
7895                               0x4044, 0, &fnum, NULL);
7896         if (!NT_STATUS_IS_OK(status)) {
7897                 printf("open failed - %s\n", nt_errstr(status));
7898                 talloc_destroy(mem_ctx);
7899                 return False;
7900         }
7901
7902         for (i = 0; i < 10; i++) {
7903                 fstring ea_name, ea_val;
7904
7905                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
7906                 memset(ea_val, (char)i+1, i+1);
7907                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
7908                 if (!NT_STATUS_IS_OK(status)) {
7909                         printf("ea_set of name %s failed - %s\n", ea_name,
7910                                nt_errstr(status));
7911                         talloc_destroy(mem_ctx);
7912                         return False;
7913                 }
7914         }
7915
7916         cli_close(cli, fnum);
7917         for (i = 0; i < 10; i++) {
7918                 fstring ea_name, ea_val;
7919
7920                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
7921                 memset(ea_val, (char)i+1, i+1);
7922                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
7923                 if (!NT_STATUS_IS_OK(status)) {
7924                         printf("ea_set of name %s failed - %s\n", ea_name,
7925                                nt_errstr(status));
7926                         talloc_destroy(mem_ctx);
7927                         return False;
7928                 }
7929         }
7930
7931         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7932         if (!NT_STATUS_IS_OK(status)) {
7933                 printf("ea_get list failed - %s\n", nt_errstr(status));
7934                 correct = False;
7935         }
7936
7937         printf("num_eas = %d\n", (int)num_eas);
7938
7939         if (num_eas != 20) {
7940                 printf("Should be 20 EA's stored... failing.\n");
7941                 correct = False;
7942         }
7943
7944         for (i = 0; i < num_eas; i++) {
7945                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7946                 dump_data(0, ea_list[i].value.data,
7947                           ea_list[i].value.length);
7948         }
7949
7950         /* Setting EA's to zero length deletes them. Test this */
7951         printf("Now deleting all EA's - case indepenent....\n");
7952
7953 #if 1
7954         cli_set_ea_path(cli, fname, "", "", 0);
7955 #else
7956         for (i = 0; i < 20; i++) {
7957                 fstring ea_name;
7958                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
7959                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
7960                 if (!NT_STATUS_IS_OK(status)) {
7961                         printf("ea_set of name %s failed - %s\n", ea_name,
7962                                nt_errstr(status));
7963                         talloc_destroy(mem_ctx);
7964                         return False;
7965                 }
7966         }
7967 #endif
7968
7969         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
7970         if (!NT_STATUS_IS_OK(status)) {
7971                 printf("ea_get list failed - %s\n", nt_errstr(status));
7972                 correct = False;
7973         }
7974
7975         printf("num_eas = %d\n", (int)num_eas);
7976         for (i = 0; i < num_eas; i++) {
7977                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
7978                 dump_data(0, ea_list[i].value.data,
7979                           ea_list[i].value.length);
7980         }
7981
7982         if (num_eas != 0) {
7983                 printf("deleting EA's failed.\n");
7984                 correct = False;
7985         }
7986
7987         /* Try and delete a non existent EA. */
7988         status = cli_set_ea_path(cli, fname, "foo", "", 0);
7989         if (!NT_STATUS_IS_OK(status)) {
7990                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
7991                        nt_errstr(status));
7992                 correct = False;
7993         }
7994
7995         talloc_destroy(mem_ctx);
7996         if (!torture_close_connection(cli)) {
7997                 correct = False;
7998         }
7999
8000         return correct;
8001 }
8002
8003 static bool run_dirtest1(int dummy)
8004 {
8005         int i;
8006         static struct cli_state *cli;
8007         uint16_t fnum;
8008         int num_seen;
8009         bool correct = True;
8010
8011         printf("starting directory test\n");
8012
8013         if (!torture_open_connection(&cli, 0)) {
8014                 return False;
8015         }
8016
8017         smbXcli_conn_set_sockopt(cli->conn, sockops);
8018
8019         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
8020         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
8021         cli_rmdir(cli, "\\LISTDIR");
8022         cli_mkdir(cli, "\\LISTDIR");
8023
8024         /* Create 1000 files and 1000 directories. */
8025         for (i=0;i<1000;i++) {
8026                 fstring fname;
8027                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
8028                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
8029                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
8030                                    0, 0, &fnum, NULL))) {
8031                         fprintf(stderr,"Failed to open %s\n", fname);
8032                         return False;
8033                 }
8034                 cli_close(cli, fnum);
8035         }
8036         for (i=0;i<1000;i++) {
8037                 fstring fname;
8038                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
8039                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
8040                         fprintf(stderr,"Failed to open %s\n", fname);
8041                         return False;
8042                 }
8043         }
8044
8045         /* Now ensure that doing an old list sees both files and directories. */
8046         num_seen = 0;
8047         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
8048         printf("num_seen = %d\n", num_seen );
8049         /* We should see 100 files + 1000 directories + . and .. */
8050         if (num_seen != 2002)
8051                 correct = False;
8052
8053         /* Ensure if we have the "must have" bits we only see the
8054          * relevent entries.
8055          */
8056         num_seen = 0;
8057         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
8058         printf("num_seen = %d\n", num_seen );
8059         if (num_seen != 1002)
8060                 correct = False;
8061
8062         num_seen = 0;
8063         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
8064         printf("num_seen = %d\n", num_seen );
8065         if (num_seen != 1000)
8066                 correct = False;
8067
8068         /* Delete everything. */
8069         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
8070         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
8071         cli_rmdir(cli, "\\LISTDIR");
8072
8073 #if 0
8074         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
8075         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
8076         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
8077 #endif
8078
8079         if (!torture_close_connection(cli)) {
8080                 correct = False;
8081         }
8082
8083         printf("finished dirtest1\n");
8084
8085         return correct;
8086 }
8087
8088 static bool run_error_map_extract(int dummy) {
8089
8090         static struct cli_state *c_dos;
8091         static struct cli_state *c_nt;
8092         NTSTATUS status;
8093
8094         uint32_t error;
8095
8096         uint32_t errnum;
8097         uint8_t errclass;
8098
8099         NTSTATUS nt_status;
8100
8101         fstring user;
8102
8103         /* NT-Error connection */
8104
8105         disable_spnego = true;
8106         if (!(c_nt = open_nbt_connection())) {
8107                 disable_spnego = false;
8108                 return False;
8109         }
8110         disable_spnego = false;
8111
8112         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
8113                                  PROTOCOL_NT1);
8114
8115         if (!NT_STATUS_IS_OK(status)) {
8116                 printf("%s rejected the NT-error negprot (%s)\n", host,
8117                        nt_errstr(status));
8118                 cli_shutdown(c_nt);
8119                 return False;
8120         }
8121
8122         status = cli_session_setup_anon(c_nt);
8123         if (!NT_STATUS_IS_OK(status)) {
8124                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
8125                 return False;
8126         }
8127
8128         /* DOS-Error connection */
8129
8130         disable_spnego = true;
8131         force_dos_errors = true;
8132         if (!(c_dos = open_nbt_connection())) {
8133                 disable_spnego = false;
8134                 force_dos_errors = false;
8135                 return False;
8136         }
8137         disable_spnego = false;
8138         force_dos_errors = false;
8139
8140         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
8141                                  PROTOCOL_NT1);
8142         if (!NT_STATUS_IS_OK(status)) {
8143                 printf("%s rejected the DOS-error negprot (%s)\n", host,
8144                        nt_errstr(status));
8145                 cli_shutdown(c_dos);
8146                 return False;
8147         }
8148
8149         status = cli_session_setup_anon(c_dos);
8150         if (!NT_STATUS_IS_OK(status)) {
8151                 printf("%s rejected the DOS-error initial session setup (%s)\n",
8152                         host, nt_errstr(status));
8153                 return False;
8154         }
8155
8156         c_nt->map_dos_errors = false;
8157         c_dos->map_dos_errors = false;
8158
8159         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
8160                 struct cli_credentials *user_creds = NULL;
8161
8162                 fstr_sprintf(user, "%X", error);
8163
8164                 user_creds = cli_session_creds_init(talloc_tos(),
8165                                                     user,
8166                                                     workgroup,
8167                                                     NULL, /* realm */
8168                                                     password,
8169                                                     false, /* use_kerberos */
8170                                                     false, /* fallback_after_kerberos */
8171                                                     false, /* use_ccache */
8172                                                     false); /* password_is_nt_hash */
8173                 if (user_creds == NULL) {
8174                         printf("cli_session_creds_init(%s) failed\n", user);
8175                         return false;
8176                 }
8177
8178                 status = cli_session_setup_creds(c_nt, user_creds);
8179                 if (NT_STATUS_IS_OK(status)) {
8180                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
8181                 }
8182
8183                 /* Case #1: 32-bit NT errors */
8184                 if (!NT_STATUS_IS_DOS(status)) {
8185                         nt_status = status;
8186                 } else {
8187                         printf("/** Dos error on NT connection! (%s) */\n", 
8188                                nt_errstr(status));
8189                         nt_status = NT_STATUS(0xc0000000);
8190                 }
8191
8192                 status = cli_session_setup_creds(c_dos, user_creds);
8193                 if (NT_STATUS_IS_OK(status)) {
8194                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
8195                 }
8196
8197                 /* Case #1: 32-bit NT errors */
8198                 if (NT_STATUS_IS_DOS(status)) {
8199                         printf("/** NT error on DOS connection! (%s) */\n", 
8200                                nt_errstr(status));
8201                         errnum = errclass = 0;
8202                 } else {
8203                         errclass = NT_STATUS_DOS_CLASS(status);
8204                         errnum = NT_STATUS_DOS_CODE(status);
8205                 }
8206
8207                 if (NT_STATUS_V(nt_status) != error) { 
8208                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
8209                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
8210                                get_nt_error_c_code(talloc_tos(), nt_status));
8211                 }
8212
8213                 printf("\t{%s,\t%s,\t%s},\n", 
8214                        smb_dos_err_class(errclass), 
8215                        smb_dos_err_name(errclass, errnum), 
8216                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
8217
8218                 TALLOC_FREE(user_creds);
8219         }
8220         return True;
8221 }
8222
8223 static bool run_sesssetup_bench(int dummy)
8224 {
8225         static struct cli_state *c;
8226         const char *fname = "\\file.dat";
8227         uint16_t fnum;
8228         NTSTATUS status;
8229         int i;
8230
8231         if (!torture_open_connection(&c, 0)) {
8232                 return false;
8233         }
8234
8235         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8236                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8237                               FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
8238         if (!NT_STATUS_IS_OK(status)) {
8239                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8240                 return false;
8241         }
8242
8243         for (i=0; i<torture_numops; i++) {
8244                 status = cli_session_setup_creds(c, torture_creds);
8245                 if (!NT_STATUS_IS_OK(status)) {
8246                         d_printf("(%s) cli_session_setup_creds failed: %s\n",
8247                                  __location__, nt_errstr(status));
8248                         return false;
8249                 }
8250
8251                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
8252
8253                 status = cli_ulogoff(c);
8254                 if (!NT_STATUS_IS_OK(status)) {
8255                         d_printf("(%s) cli_ulogoff failed: %s\n",
8256                                  __location__, nt_errstr(status));
8257                         return false;
8258                 }
8259         }
8260
8261         return true;
8262 }
8263
8264 static bool subst_test(const char *str, const char *user, const char *domain,
8265                        uid_t uid, gid_t gid, const char *expected)
8266 {
8267         char *subst;
8268         bool result = true;
8269
8270         subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
8271
8272         if (strcmp(subst, expected) != 0) {
8273                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
8274                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
8275                        expected);
8276                 result = false;
8277         }
8278
8279         TALLOC_FREE(subst);
8280         return result;
8281 }
8282
8283 static void chain1_open_completion(struct tevent_req *req)
8284 {
8285         uint16_t fnum;
8286         NTSTATUS status;
8287         status = cli_openx_recv(req, &fnum);
8288         TALLOC_FREE(req);
8289
8290         d_printf("cli_openx_recv returned %s: %d\n",
8291                  nt_errstr(status),
8292                  NT_STATUS_IS_OK(status) ? fnum : -1);
8293 }
8294
8295 static void chain1_write_completion(struct tevent_req *req)
8296 {
8297         size_t written;
8298         NTSTATUS status;
8299         status = cli_write_andx_recv(req, &written);
8300         TALLOC_FREE(req);
8301
8302         d_printf("cli_write_andx_recv returned %s: %d\n",
8303                  nt_errstr(status),
8304                  NT_STATUS_IS_OK(status) ? (int)written : -1);
8305 }
8306
8307 static void chain1_close_completion(struct tevent_req *req)
8308 {
8309         NTSTATUS status;
8310         bool *done = (bool *)tevent_req_callback_data_void(req);
8311
8312         status = cli_close_recv(req);
8313         *done = true;
8314
8315         TALLOC_FREE(req);
8316
8317         d_printf("cli_close returned %s\n", nt_errstr(status));
8318 }
8319
8320 static bool run_chain1(int dummy)
8321 {
8322         struct cli_state *cli1;
8323         struct tevent_context *evt = samba_tevent_context_init(NULL);
8324         struct tevent_req *reqs[3], *smbreqs[3];
8325         bool done = false;
8326         const char *str = "foobar";
8327         const char *fname = "\\test_chain";
8328         NTSTATUS status;
8329
8330         printf("starting chain1 test\n");
8331         if (!torture_open_connection(&cli1, 0)) {
8332                 return False;
8333         }
8334
8335         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8336
8337         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8338
8339         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
8340                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
8341         if (reqs[0] == NULL) return false;
8342         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
8343
8344
8345         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
8346                                         (const uint8_t *)str, 0, strlen(str)+1,
8347                                         smbreqs, 1, &smbreqs[1]);
8348         if (reqs[1] == NULL) return false;
8349         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
8350
8351         reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
8352         if (reqs[2] == NULL) return false;
8353         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
8354
8355         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8356         if (!NT_STATUS_IS_OK(status)) {
8357                 return false;
8358         }
8359
8360         while (!done) {
8361                 tevent_loop_once(evt);
8362         }
8363
8364         torture_close_connection(cli1);
8365         return True;
8366 }
8367
8368 static void chain2_sesssetup_completion(struct tevent_req *req)
8369 {
8370         NTSTATUS status;
8371         status = cli_session_setup_guest_recv(req);
8372         d_printf("sesssetup returned %s\n", nt_errstr(status));
8373 }
8374
8375 static void chain2_tcon_completion(struct tevent_req *req)
8376 {
8377         bool *done = (bool *)tevent_req_callback_data_void(req);
8378         NTSTATUS status;
8379         status = cli_tcon_andx_recv(req);
8380         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
8381         *done = true;
8382 }
8383
8384 static bool run_chain2(int dummy)
8385 {
8386         struct cli_state *cli1;
8387         struct tevent_context *evt = samba_tevent_context_init(NULL);
8388         struct tevent_req *reqs[2], *smbreqs[2];
8389         bool done = false;
8390         NTSTATUS status;
8391         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
8392
8393         printf("starting chain2 test\n");
8394         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
8395                                       port_to_use, SMB_SIGNING_DEFAULT, flags);
8396         if (!NT_STATUS_IS_OK(status)) {
8397                 return False;
8398         }
8399
8400         smbXcli_conn_set_sockopt(cli1->conn, sockops);
8401
8402         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
8403                                                  &smbreqs[0]);
8404         if (reqs[0] == NULL) return false;
8405         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
8406
8407         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
8408                                        "?????", NULL, 0, &smbreqs[1]);
8409         if (reqs[1] == NULL) return false;
8410         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
8411
8412         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
8413         if (!NT_STATUS_IS_OK(status)) {
8414                 return false;
8415         }
8416
8417         while (!done) {
8418                 tevent_loop_once(evt);
8419         }
8420
8421         torture_close_connection(cli1);
8422         return True;
8423 }
8424
8425
8426 struct torture_createdel_state {
8427         struct tevent_context *ev;
8428         struct cli_state *cli;
8429 };
8430
8431 static void torture_createdel_created(struct tevent_req *subreq);
8432 static void torture_createdel_closed(struct tevent_req *subreq);
8433
8434 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
8435                                                  struct tevent_context *ev,
8436                                                  struct cli_state *cli,
8437                                                  const char *name)
8438 {
8439         struct tevent_req *req, *subreq;
8440         struct torture_createdel_state *state;
8441
8442         req = tevent_req_create(mem_ctx, &state,
8443                                 struct torture_createdel_state);
8444         if (req == NULL) {
8445                 return NULL;
8446         }
8447         state->ev = ev;
8448         state->cli = cli;
8449
8450         subreq = cli_ntcreate_send(
8451                 state, ev, cli, name, 0,
8452                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
8453                 FILE_ATTRIBUTE_NORMAL,
8454                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8455                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
8456                 SMB2_IMPERSONATION_IMPERSONATION, 0);
8457
8458         if (tevent_req_nomem(subreq, req)) {
8459                 return tevent_req_post(req, ev);
8460         }
8461         tevent_req_set_callback(subreq, torture_createdel_created, req);
8462         return req;
8463 }
8464
8465 static void torture_createdel_created(struct tevent_req *subreq)
8466 {
8467         struct tevent_req *req = tevent_req_callback_data(
8468                 subreq, struct tevent_req);
8469         struct torture_createdel_state *state = tevent_req_data(
8470                 req, struct torture_createdel_state);
8471         NTSTATUS status;
8472         uint16_t fnum;
8473
8474         status = cli_ntcreate_recv(subreq, &fnum, NULL);
8475         TALLOC_FREE(subreq);
8476         if (tevent_req_nterror(req, status)) {
8477                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
8478                            nt_errstr(status)));
8479                 return;
8480         }
8481
8482         subreq = cli_close_send(state, state->ev, state->cli, fnum);
8483         if (tevent_req_nomem(subreq, req)) {
8484                 return;
8485         }
8486         tevent_req_set_callback(subreq, torture_createdel_closed, req);
8487 }
8488
8489 static void torture_createdel_closed(struct tevent_req *subreq)
8490 {
8491         struct tevent_req *req = tevent_req_callback_data(
8492                 subreq, struct tevent_req);
8493         NTSTATUS status;
8494
8495         status = cli_close_recv(subreq);
8496         if (tevent_req_nterror(req, status)) {
8497                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
8498                 return;
8499         }
8500         tevent_req_done(req);
8501 }
8502
8503 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
8504 {
8505         return tevent_req_simple_recv_ntstatus(req);
8506 }
8507
8508 struct torture_createdels_state {
8509         struct tevent_context *ev;
8510         struct cli_state *cli;
8511         const char *base_name;
8512         int sent;
8513         int received;
8514         int num_files;
8515         struct tevent_req **reqs;
8516 };
8517
8518 static void torture_createdels_done(struct tevent_req *subreq);
8519
8520 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
8521                                                   struct tevent_context *ev,
8522                                                   struct cli_state *cli,
8523                                                   const char *base_name,
8524                                                   int num_parallel,
8525                                                   int num_files)
8526 {
8527         struct tevent_req *req;
8528         struct torture_createdels_state *state;
8529         int i;
8530
8531         req = tevent_req_create(mem_ctx, &state,
8532                                 struct torture_createdels_state);
8533         if (req == NULL) {
8534                 return NULL;
8535         }
8536         state->ev = ev;
8537         state->cli = cli;
8538         state->base_name = talloc_strdup(state, base_name);
8539         if (tevent_req_nomem(state->base_name, req)) {
8540                 return tevent_req_post(req, ev);
8541         }
8542         state->num_files = MAX(num_parallel, num_files);
8543         state->sent = 0;
8544         state->received = 0;
8545
8546         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
8547         if (tevent_req_nomem(state->reqs, req)) {
8548                 return tevent_req_post(req, ev);
8549         }
8550
8551         for (i=0; i<num_parallel; i++) {
8552                 char *name;
8553
8554                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8555                                        state->sent);
8556                 if (tevent_req_nomem(name, req)) {
8557                         return tevent_req_post(req, ev);
8558                 }
8559                 state->reqs[i] = torture_createdel_send(
8560                         state->reqs, state->ev, state->cli, name);
8561                 if (tevent_req_nomem(state->reqs[i], req)) {
8562                         return tevent_req_post(req, ev);
8563                 }
8564                 name = talloc_move(state->reqs[i], &name);
8565                 tevent_req_set_callback(state->reqs[i],
8566                                         torture_createdels_done, req);
8567                 state->sent += 1;
8568         }
8569         return req;
8570 }
8571
8572 static void torture_createdels_done(struct tevent_req *subreq)
8573 {
8574         struct tevent_req *req = tevent_req_callback_data(
8575                 subreq, struct tevent_req);
8576         struct torture_createdels_state *state = tevent_req_data(
8577                 req, struct torture_createdels_state);
8578         size_t num_parallel = talloc_array_length(state->reqs);
8579         NTSTATUS status;
8580         char *name;
8581         int i;
8582
8583         status = torture_createdel_recv(subreq);
8584         if (!NT_STATUS_IS_OK(status)){
8585                 DEBUG(10, ("torture_createdel_recv returned %s\n",
8586                            nt_errstr(status)));
8587                 TALLOC_FREE(subreq);
8588                 tevent_req_nterror(req, status);
8589                 return;
8590         }
8591
8592         for (i=0; i<num_parallel; i++) {
8593                 if (subreq == state->reqs[i]) {
8594                         break;
8595                 }
8596         }
8597         if (i == num_parallel) {
8598                 DEBUG(10, ("received something we did not send\n"));
8599                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
8600                 return;
8601         }
8602         TALLOC_FREE(state->reqs[i]);
8603
8604         if (state->sent >= state->num_files) {
8605                 tevent_req_done(req);
8606                 return;
8607         }
8608
8609         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
8610                                state->sent);
8611         if (tevent_req_nomem(name, req)) {
8612                 return;
8613         }
8614         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
8615                                                 state->cli, name);
8616         if (tevent_req_nomem(state->reqs[i], req)) {
8617                 return;
8618         }
8619         name = talloc_move(state->reqs[i], &name);
8620         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
8621         state->sent += 1;
8622 }
8623
8624 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
8625 {
8626         return tevent_req_simple_recv_ntstatus(req);
8627 }
8628
8629 struct swallow_notify_state {
8630         struct tevent_context *ev;
8631         struct cli_state *cli;
8632         uint16_t fnum;
8633         uint32_t completion_filter;
8634         bool recursive;
8635         bool (*fn)(uint32_t action, const char *name, void *priv);
8636         void *priv;
8637 };
8638
8639 static void swallow_notify_done(struct tevent_req *subreq);
8640
8641 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
8642                                               struct tevent_context *ev,
8643                                               struct cli_state *cli,
8644                                               uint16_t fnum,
8645                                               uint32_t completion_filter,
8646                                               bool recursive,
8647                                               bool (*fn)(uint32_t action,
8648                                                          const char *name,
8649                                                          void *priv),
8650                                               void *priv)
8651 {
8652         struct tevent_req *req, *subreq;
8653         struct swallow_notify_state *state;
8654
8655         req = tevent_req_create(mem_ctx, &state,
8656                                 struct swallow_notify_state);
8657         if (req == NULL) {
8658                 return NULL;
8659         }
8660         state->ev = ev;
8661         state->cli = cli;
8662         state->fnum = fnum;
8663         state->completion_filter = completion_filter;
8664         state->recursive = recursive;
8665         state->fn = fn;
8666         state->priv = priv;
8667
8668         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8669                                  0xffff, state->completion_filter,
8670                                  state->recursive);
8671         if (tevent_req_nomem(subreq, req)) {
8672                 return tevent_req_post(req, ev);
8673         }
8674         tevent_req_set_callback(subreq, swallow_notify_done, req);
8675         return req;
8676 }
8677
8678 static void swallow_notify_done(struct tevent_req *subreq)
8679 {
8680         struct tevent_req *req = tevent_req_callback_data(
8681                 subreq, struct tevent_req);
8682         struct swallow_notify_state *state = tevent_req_data(
8683                 req, struct swallow_notify_state);
8684         NTSTATUS status;
8685         uint32_t i, num_changes;
8686         struct notify_change *changes;
8687
8688         status = cli_notify_recv(subreq, state, &num_changes, &changes);
8689         TALLOC_FREE(subreq);
8690         if (!NT_STATUS_IS_OK(status)) {
8691                 DEBUG(10, ("cli_notify_recv returned %s\n",
8692                            nt_errstr(status)));
8693                 tevent_req_nterror(req, status);
8694                 return;
8695         }
8696
8697         for (i=0; i<num_changes; i++) {
8698                 state->fn(changes[i].action, changes[i].name, state->priv);
8699         }
8700         TALLOC_FREE(changes);
8701
8702         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
8703                                  0xffff, state->completion_filter,
8704                                  state->recursive);
8705         if (tevent_req_nomem(subreq, req)) {
8706                 return;
8707         }
8708         tevent_req_set_callback(subreq, swallow_notify_done, req);
8709 }
8710
8711 static bool print_notifies(uint32_t action, const char *name, void *priv)
8712 {
8713         if (DEBUGLEVEL > 5) {
8714                 d_printf("%d %s\n", (int)action, name);
8715         }
8716         return true;
8717 }
8718
8719 static void notify_bench_done(struct tevent_req *req)
8720 {
8721         int *num_finished = (int *)tevent_req_callback_data_void(req);
8722         *num_finished += 1;
8723 }
8724
8725 static bool run_notify_bench(int dummy)
8726 {
8727         const char *dname = "\\notify-bench";
8728         struct tevent_context *ev;
8729         NTSTATUS status;
8730         uint16_t dnum;
8731         struct tevent_req *req1;
8732         struct tevent_req *req2 = NULL;
8733         int i, num_unc_names;
8734         int num_finished = 0;
8735
8736         printf("starting notify-bench test\n");
8737
8738         if (use_multishare_conn) {
8739                 char **unc_list;
8740                 unc_list = file_lines_load(multishare_conn_fname,
8741                                            &num_unc_names, 0, NULL);
8742                 if (!unc_list || num_unc_names <= 0) {
8743                         d_printf("Failed to load unc names list from '%s'\n",
8744                                  multishare_conn_fname);
8745                         return false;
8746                 }
8747                 TALLOC_FREE(unc_list);
8748         } else {
8749                 num_unc_names = 1;
8750         }
8751
8752         ev = samba_tevent_context_init(talloc_tos());
8753         if (ev == NULL) {
8754                 d_printf("tevent_context_init failed\n");
8755                 return false;
8756         }
8757
8758         for (i=0; i<num_unc_names; i++) {
8759                 struct cli_state *cli;
8760                 char *base_fname;
8761
8762                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
8763                                              dname, i);
8764                 if (base_fname == NULL) {
8765                         return false;
8766                 }
8767
8768                 if (!torture_open_connection(&cli, i)) {
8769                         return false;
8770                 }
8771
8772                 status = cli_ntcreate(cli, dname, 0,
8773                                       MAXIMUM_ALLOWED_ACCESS,
8774                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
8775                                       FILE_SHARE_DELETE,
8776                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
8777                                       &dnum, NULL);
8778
8779                 if (!NT_STATUS_IS_OK(status)) {
8780                         d_printf("Could not create %s: %s\n", dname,
8781                                  nt_errstr(status));
8782                         return false;
8783                 }
8784
8785                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
8786                                            FILE_NOTIFY_CHANGE_FILE_NAME |
8787                                            FILE_NOTIFY_CHANGE_DIR_NAME |
8788                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
8789                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
8790                                            false, print_notifies, NULL);
8791                 if (req1 == NULL) {
8792                         d_printf("Could not create notify request\n");
8793                         return false;
8794                 }
8795
8796                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
8797                                                base_fname, 10, torture_numops);
8798                 if (req2 == NULL) {
8799                         d_printf("Could not create createdels request\n");
8800                         return false;
8801                 }
8802                 TALLOC_FREE(base_fname);
8803
8804                 tevent_req_set_callback(req2, notify_bench_done,
8805                                         &num_finished);
8806         }
8807
8808         while (num_finished < num_unc_names) {
8809                 int ret;
8810                 ret = tevent_loop_once(ev);
8811                 if (ret != 0) {
8812                         d_printf("tevent_loop_once failed\n");
8813                         return false;
8814                 }
8815         }
8816
8817         if (!tevent_req_poll(req2, ev)) {
8818                 d_printf("tevent_req_poll failed\n");
8819         }
8820
8821         status = torture_createdels_recv(req2);
8822         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
8823
8824         return true;
8825 }
8826
8827 static bool run_mangle1(int dummy)
8828 {
8829         struct cli_state *cli;
8830         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
8831         uint16_t fnum;
8832         fstring alt_name;
8833         NTSTATUS status;
8834         time_t change_time, access_time, write_time;
8835         off_t size;
8836         uint16_t mode;
8837
8838         printf("starting mangle1 test\n");
8839         if (!torture_open_connection(&cli, 0)) {
8840                 return False;
8841         }
8842
8843         smbXcli_conn_set_sockopt(cli->conn, sockops);
8844
8845         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8846                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8847                               0, 0, &fnum, NULL);
8848         if (!NT_STATUS_IS_OK(status)) {
8849                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
8850                 return false;
8851         }
8852         cli_close(cli, fnum);
8853
8854         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
8855         if (!NT_STATUS_IS_OK(status)) {
8856                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
8857                          nt_errstr(status));
8858                 return false;
8859         }
8860         d_printf("alt_name: %s\n", alt_name);
8861
8862         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
8863         if (!NT_STATUS_IS_OK(status)) {
8864                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
8865                          nt_errstr(status));
8866                 return false;
8867         }
8868         cli_close(cli, fnum);
8869
8870         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
8871                                 &write_time, &size, &mode);
8872         if (!NT_STATUS_IS_OK(status)) {
8873                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
8874                          nt_errstr(status));
8875                 return false;
8876         }
8877
8878         return true;
8879 }
8880
8881 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
8882                                                  struct file_info *f,
8883                                                  const char *mask,
8884                                                  void *state)
8885 {
8886         if (f->short_name == NULL) {
8887                 return NT_STATUS_OK;
8888         }
8889
8890         if (strlen(f->short_name) == 0) {
8891                 return NT_STATUS_OK;
8892         }
8893
8894         printf("unexpected shortname: %s\n", f->short_name);
8895
8896         return NT_STATUS_OBJECT_NAME_INVALID;
8897 }
8898
8899 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
8900                                             struct file_info *f,
8901                                             const char *mask,
8902                                             void *state)
8903 {
8904         char *name = state;
8905
8906         printf("name: %s\n", f->name);
8907         fstrcpy(name, f->name);
8908         return NT_STATUS_OK;
8909 }
8910
8911 static bool run_mangle_illegal(int dummy)
8912 {
8913         struct cli_state *cli = NULL;
8914         struct cli_state *cli_posix = NULL;
8915         const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
8916         const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
8917         char *mangled_path = NULL;
8918         uint16_t fnum;
8919         fstring name;
8920         fstring alt_name;
8921         NTSTATUS status;
8922
8923         printf("starting mangle-illegal test\n");
8924
8925         if (!torture_open_connection(&cli, 0)) {
8926                 return False;
8927         }
8928
8929         smbXcli_conn_set_sockopt(cli->conn, sockops);
8930
8931         if (!torture_open_connection(&cli_posix, 0)) {
8932                 return false;
8933         }
8934
8935         smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
8936
8937         status = torture_setup_unix_extensions(cli_posix);
8938         if (!NT_STATUS_IS_OK(status)) {
8939                 return false;
8940         }
8941
8942         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
8943         status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
8944         if (!NT_STATUS_IS_OK(status)) {
8945                 printf("mkdir1 failed : %s\n", nt_errstr(status));
8946                 return False;
8947         }
8948
8949         /*
8950          * Create a file with illegal NTFS characters and test that we
8951          * get a usable mangled name
8952          */
8953
8954         cli_setatr(cli_posix, illegal_fname, 0, 0);
8955         cli_posix_unlink(cli_posix, illegal_fname);
8956
8957         status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
8958                                 0600, &fnum);
8959         if (!NT_STATUS_IS_OK(status)) {
8960                 printf("POSIX create of %s failed (%s)\n",
8961                        illegal_fname, nt_errstr(status));
8962                 return false;
8963         }
8964
8965         status = cli_close(cli_posix, fnum);
8966         if (!NT_STATUS_IS_OK(status)) {
8967                 printf("close failed (%s)\n", nt_errstr(status));
8968                 return false;
8969         }
8970
8971         status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
8972         if (!NT_STATUS_IS_OK(status)) {
8973                 d_printf("cli_list failed: %s\n", nt_errstr(status));
8974                 return false;
8975         }
8976
8977         mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
8978         if (mangled_path == NULL) {
8979                 return false;
8980         }
8981
8982         status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
8983         if (!NT_STATUS_IS_OK(status)) {
8984                 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
8985                 TALLOC_FREE(mangled_path);
8986                 return false;
8987         }
8988         TALLOC_FREE(mangled_path);
8989         cli_close(cli, fnum);
8990
8991         cli_setatr(cli_posix, illegal_fname, 0, 0);
8992         cli_posix_unlink(cli_posix, illegal_fname);
8993
8994         /*
8995          * Create a file with a long name and check that we got *no* short name.
8996          */
8997
8998         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
8999                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9000                               0, 0, &fnum, NULL);
9001         if (!NT_STATUS_IS_OK(status)) {
9002                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
9003                 return false;
9004         }
9005         cli_close(cli, fnum);
9006
9007         status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
9008         if (!NT_STATUS_IS_OK(status)) {
9009                 d_printf("cli_list failed\n");
9010                 return false;
9011         }
9012
9013         cli_unlink(cli, fname, 0);
9014         cli_rmdir(cli, "\\MANGLE_ILLEGAL");
9015
9016         if (!torture_close_connection(cli_posix)) {
9017                 return false;
9018         }
9019
9020         if (!torture_close_connection(cli)) {
9021                 return false;
9022         }
9023
9024         return true;
9025 }
9026
9027 static size_t null_source(uint8_t *buf, size_t n, void *priv)
9028 {
9029         size_t *to_pull = (size_t *)priv;
9030         size_t thistime = *to_pull;
9031
9032         thistime = MIN(thistime, n);
9033         if (thistime == 0) {
9034                 return 0;
9035         }
9036
9037         memset(buf, 0, thistime);
9038         *to_pull -= thistime;
9039         return thistime;
9040 }
9041
9042 static bool run_windows_write(int dummy)
9043 {
9044         struct cli_state *cli1;
9045         uint16_t fnum;
9046         int i;
9047         bool ret = false;
9048         const char *fname = "\\writetest.txt";
9049         struct timeval start_time;
9050         double seconds;
9051         double kbytes;
9052         NTSTATUS status;
9053
9054         printf("starting windows_write test\n");
9055         if (!torture_open_connection(&cli1, 0)) {
9056                 return False;
9057         }
9058
9059         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9060         if (!NT_STATUS_IS_OK(status)) {
9061                 printf("open failed (%s)\n", nt_errstr(status));
9062                 return False;
9063         }
9064
9065         smbXcli_conn_set_sockopt(cli1->conn, sockops);
9066
9067         start_time = timeval_current();
9068
9069         for (i=0; i<torture_numops; i++) {
9070                 uint8_t c = 0;
9071                 off_t start = i * torture_blocksize;
9072                 size_t to_pull = torture_blocksize - 1;
9073
9074                 status = cli_writeall(cli1, fnum, 0, &c,
9075                                       start + torture_blocksize - 1, 1, NULL);
9076                 if (!NT_STATUS_IS_OK(status)) {
9077                         printf("cli_write failed: %s\n", nt_errstr(status));
9078                         goto fail;
9079                 }
9080
9081                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
9082                                   null_source, &to_pull);
9083                 if (!NT_STATUS_IS_OK(status)) {
9084                         printf("cli_push returned: %s\n", nt_errstr(status));
9085                         goto fail;
9086                 }
9087         }
9088
9089         seconds = timeval_elapsed(&start_time);
9090         kbytes = (double)torture_blocksize * torture_numops;
9091         kbytes /= 1024;
9092
9093         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
9094                (double)seconds, (int)(kbytes/seconds));
9095
9096         ret = true;
9097  fail:
9098         cli_close(cli1, fnum);
9099         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9100         torture_close_connection(cli1);
9101         return ret;
9102 }
9103
9104 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
9105 {
9106         size_t max_pdu = 0x1FFFF;
9107
9108         if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
9109                 max_pdu = 0xFFFFFF;
9110         }
9111
9112         if (smb1cli_conn_signing_is_active(cli->conn)) {
9113                 max_pdu = 0x1FFFF;
9114         }
9115
9116         if (smb1cli_conn_encryption_on(cli->conn)) {
9117                 max_pdu = CLI_BUFFER_SIZE;
9118         }
9119
9120         if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
9121                 len_requested &= 0xFFFF;
9122         }
9123
9124         return MIN(len_requested,
9125                    max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
9126 }
9127
9128 static bool check_read_call(struct cli_state *cli,
9129                             uint16_t fnum,
9130                             uint8_t *buf,
9131                             size_t len_requested)
9132 {
9133         NTSTATUS status;
9134         struct tevent_req *subreq = NULL;
9135         ssize_t len_read = 0;
9136         size_t len_expected = 0;
9137         struct tevent_context *ev = NULL;
9138
9139         ev = samba_tevent_context_init(talloc_tos());
9140         if (ev == NULL) {
9141                 return false;
9142         }
9143
9144         subreq = cli_read_andx_send(talloc_tos(),
9145                                     ev,
9146                                     cli,
9147                                     fnum,
9148                                     0,
9149                                     len_requested);
9150
9151         if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
9152                 return false;
9153         }
9154
9155         status = cli_read_andx_recv(subreq, &len_read, &buf);
9156         if (!NT_STATUS_IS_OK(status)) {
9157                 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
9158                 return false;
9159         }
9160
9161         TALLOC_FREE(subreq);
9162         TALLOC_FREE(ev);
9163
9164         len_expected = calc_expected_return(cli, len_requested);
9165
9166         if (len_expected > 0x10000 && len_read == 0x10000) {
9167                 /* Windows servers only return a max of 0x10000,
9168                    doesn't matter if you set CAP_LARGE_READX in
9169                    the client sessionsetupX call or not. */
9170                 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
9171                         (unsigned int)len_requested);
9172         } else if (len_read != len_expected) {
9173                 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
9174                         (unsigned int)len_requested,
9175                         (unsigned int)len_read,
9176                         (unsigned int)len_expected);
9177                 return false;
9178         } else {
9179                 d_printf("Correct read reply.\n");
9180         }
9181
9182         return true;
9183 }
9184
9185 /* Test large readX variants. */
9186 static bool large_readx_tests(struct cli_state *cli,
9187                                 uint16_t fnum,
9188                                 uint8_t *buf)
9189 {
9190         /* A read of 0xFFFF0001 should *always* return 1 byte. */
9191         if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
9192                 return false;
9193         }
9194         /* A read of 0x10000 should return 0x10000 bytes. */
9195         if (check_read_call(cli, fnum, buf,    0x10000) == false) {
9196                 return false;
9197         }
9198         /* A read of 0x10000 should return 0x10001 bytes. */
9199         if (check_read_call(cli, fnum, buf,    0x10001) == false) {
9200                 return false;
9201         }
9202         /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
9203            the requested number of bytes. */
9204         if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
9205                 return false;
9206         }
9207         /* A read of 1MB should return 1MB bytes (on Samba). */
9208         if (check_read_call(cli, fnum, buf,   0x100000) == false) {
9209                 return false;
9210         }
9211
9212         if (check_read_call(cli, fnum, buf,    0x20001) == false) {
9213                 return false;
9214         }
9215         if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
9216                 return false;
9217         }
9218         if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
9219                 return false;
9220         }
9221         return true;
9222 }
9223
9224 static bool run_large_readx(int dummy)
9225 {
9226         uint8_t *buf = NULL;
9227         struct cli_state *cli1 = NULL;
9228         struct cli_state *cli2 = NULL;
9229         bool correct = false;
9230         const char *fname = "\\large_readx.dat";
9231         NTSTATUS status;
9232         uint16_t fnum1 = UINT16_MAX;
9233         uint32_t normal_caps = 0;
9234         size_t file_size = 20*1024*1024;
9235         TALLOC_CTX *frame = talloc_stackframe();
9236         size_t i;
9237         struct {
9238                 const char *name;
9239                 enum smb_signing_setting signing_setting;
9240                 enum protocol_types protocol;
9241         } runs[] = {
9242                 {
9243                         .name = "NT1",
9244                         .signing_setting = SMB_SIGNING_IF_REQUIRED,
9245                         .protocol = PROTOCOL_NT1,
9246                 },{
9247                         .name = "NT1 - SIGNING_REQUIRED",
9248                         .signing_setting = SMB_SIGNING_REQUIRED,
9249                         .protocol = PROTOCOL_NT1,
9250                 },
9251         };
9252
9253         printf("starting large_readx test\n");
9254
9255         if (!torture_open_connection(&cli1, 0)) {
9256                 goto out;
9257         }
9258
9259         normal_caps = smb1cli_conn_capabilities(cli1->conn);
9260
9261         if (!(normal_caps & CAP_LARGE_READX)) {
9262                 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9263                         (unsigned int)normal_caps);
9264                 goto out;
9265         }
9266
9267         /* Create a file of size 4MB. */
9268         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
9269                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9270                         0, 0, &fnum1, NULL);
9271
9272         if (!NT_STATUS_IS_OK(status)) {
9273                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
9274                 goto out;
9275         }
9276
9277         /* Write file_size bytes. */
9278         buf = talloc_zero_array(frame, uint8_t, file_size);
9279         if (buf == NULL) {
9280                 goto out;
9281         }
9282
9283         status = cli_writeall(cli1,
9284                               fnum1,
9285                               0,
9286                               buf,
9287                               0,
9288                               file_size,
9289                               NULL);
9290         if (!NT_STATUS_IS_OK(status)) {
9291                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9292                 goto out;
9293         }
9294
9295         status = cli_close(cli1, fnum1);
9296         if (!NT_STATUS_IS_OK(status)) {
9297                 d_printf("cli_close failed: %s\n", nt_errstr(status));
9298                 goto out;
9299         }
9300
9301         fnum1 = UINT16_MAX;
9302
9303         for (i=0; i < ARRAY_SIZE(runs); i++) {
9304                 enum smb_signing_setting saved_signing_setting = signing_state;
9305                 uint16_t fnum2 = -1;
9306
9307                 if (do_encrypt &&
9308                     (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
9309                 {
9310                         d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
9311                         continue;
9312                 }
9313
9314                 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
9315
9316                 signing_state = runs[i].signing_setting;
9317                 cli2 = open_nbt_connection();
9318                 signing_state = saved_signing_setting;
9319                 if (cli2 == NULL) {
9320                         goto out;
9321                 }
9322
9323                 status = smbXcli_negprot(cli2->conn,
9324                                          cli2->timeout,
9325                                          runs[i].protocol,
9326                                          runs[i].protocol);
9327                 if (!NT_STATUS_IS_OK(status)) {
9328                         goto out;
9329                 }
9330
9331                 status = cli_session_setup_creds(cli2, torture_creds);
9332                 if (!NT_STATUS_IS_OK(status)) {
9333                         goto out;
9334                 }
9335
9336                 status = cli_tree_connect(cli2,
9337                                         share,
9338                                         "?????",
9339                                         password);
9340                 if (!NT_STATUS_IS_OK(status)) {
9341                         goto out;
9342                 }
9343
9344                 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
9345
9346                 normal_caps = smb1cli_conn_capabilities(cli2->conn);
9347
9348                 if (!(normal_caps & CAP_LARGE_READX)) {
9349                         d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
9350                                 (unsigned int)normal_caps);
9351                         goto out;
9352                 }
9353
9354                 if (do_encrypt) {
9355                         if (force_cli_encryption(cli2, share) == false) {
9356                                 goto out;
9357                         }
9358                 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
9359                         uint16_t major, minor;
9360                         uint32_t caplow, caphigh;
9361
9362                         status = cli_unix_extensions_version(cli2,
9363                                                              &major, &minor,
9364                                                              &caplow, &caphigh);
9365                         if (!NT_STATUS_IS_OK(status)) {
9366                                 goto out;
9367                         }
9368                 }
9369
9370                 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
9371                                 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
9372                                 0, 0, &fnum2, NULL);
9373                 if (!NT_STATUS_IS_OK(status)) {
9374                         d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
9375                         goto out;
9376                 }
9377
9378                 /* All reads must return less than file_size bytes. */
9379                 if (!large_readx_tests(cli2, fnum2, buf)) {
9380                         goto out;
9381                 }
9382
9383                 status = cli_close(cli2, fnum2);
9384                 if (!NT_STATUS_IS_OK(status)) {
9385                         d_printf("cli_close failed: %s\n", nt_errstr(status));
9386                         goto out;
9387                 }
9388                 fnum2 = -1;
9389
9390                 if (!torture_close_connection(cli2)) {
9391                         goto out;
9392                 }
9393                 cli2 = NULL;
9394         }
9395
9396         correct = true;
9397         printf("Success on large_readx test\n");
9398
9399   out:
9400
9401         if (cli2) {
9402                 if (!torture_close_connection(cli2)) {
9403                         correct = false;
9404                 }
9405         }
9406
9407         if (cli1) {
9408                 if (fnum1 != UINT16_MAX) {
9409                         status = cli_close(cli1, fnum1);
9410                         if (!NT_STATUS_IS_OK(status)) {
9411                                 d_printf("cli_close failed: %s\n", nt_errstr(status));
9412                         }
9413                         fnum1 = UINT16_MAX;
9414                 }
9415
9416                 status = cli_unlink(cli1, fname,
9417                                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9418                 if (!NT_STATUS_IS_OK(status)) {
9419                         printf("unlink failed (%s)\n", nt_errstr(status));
9420                 }
9421
9422                 if (!torture_close_connection(cli1)) {
9423                         correct = false;
9424                 }
9425         }
9426
9427         TALLOC_FREE(frame);
9428
9429         printf("finished large_readx test\n");
9430         return correct;
9431 }
9432
9433 static bool run_cli_echo(int dummy)
9434 {
9435         struct cli_state *cli;
9436         NTSTATUS status;
9437
9438         printf("starting cli_echo test\n");
9439         if (!torture_open_connection(&cli, 0)) {
9440                 return false;
9441         }
9442         smbXcli_conn_set_sockopt(cli->conn, sockops);
9443
9444         status = cli_echo(cli, 5, data_blob_const("hello", 5));
9445
9446         d_printf("cli_echo returned %s\n", nt_errstr(status));
9447
9448         torture_close_connection(cli);
9449         return NT_STATUS_IS_OK(status);
9450 }
9451
9452 static int splice_status(off_t written, void *priv)
9453 {
9454         return true;
9455 }
9456
9457 static bool run_cli_splice(int dummy)
9458 {
9459         uint8_t *buf = NULL;
9460         struct cli_state *cli1 = NULL;
9461         bool correct = false;
9462         const char *fname_src = "\\splice_src.dat";
9463         const char *fname_dst = "\\splice_dst.dat";
9464         NTSTATUS status;
9465         uint16_t fnum1 = UINT16_MAX;
9466         uint16_t fnum2 = UINT16_MAX;
9467         size_t file_size = 2*1024*1024;
9468         size_t splice_size = 1*1024*1024 + 713;
9469         MD5_CTX md5_ctx;
9470         uint8_t digest1[16], digest2[16];
9471         off_t written = 0;
9472         size_t nread = 0;
9473         TALLOC_CTX *frame = talloc_stackframe();
9474
9475         printf("starting cli_splice test\n");
9476
9477         if (!torture_open_connection(&cli1, 0)) {
9478                 goto out;
9479         }
9480
9481         cli_unlink(cli1, fname_src,
9482                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9483         cli_unlink(cli1, fname_dst,
9484                 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9485
9486         /* Create a file */
9487         status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
9488                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9489                         0, 0, &fnum1, NULL);
9490
9491         if (!NT_STATUS_IS_OK(status)) {
9492                 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
9493                 goto out;
9494         }
9495
9496         /* Write file_size bytes - must be bigger than splice_size. */
9497         buf = talloc_zero_array(frame, uint8_t, file_size);
9498         if (buf == NULL) {
9499                 d_printf("talloc_fail\n");
9500                 goto out;
9501         }
9502
9503         /* Fill it with random numbers. */
9504         generate_random_buffer(buf, file_size);
9505
9506         /* MD5 the first 1MB + 713 bytes. */
9507         MD5Init(&md5_ctx);
9508         MD5Update(&md5_ctx, buf, splice_size);
9509         MD5Final(digest1, &md5_ctx);
9510
9511         status = cli_writeall(cli1,
9512                               fnum1,
9513                               0,
9514                               buf,
9515                               0,
9516                               file_size,
9517                               NULL);
9518         if (!NT_STATUS_IS_OK(status)) {
9519                 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
9520                 goto out;
9521         }
9522
9523         status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
9524                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
9525                         0, 0, &fnum2, NULL);
9526
9527         if (!NT_STATUS_IS_OK(status)) {
9528                 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
9529                 goto out;
9530         }
9531
9532         /* Now splice 1MB + 713 bytes. */
9533         status = cli_splice(cli1,
9534                                 cli1,
9535                                 fnum1,
9536                                 fnum2,
9537                                 splice_size,
9538                                 0,
9539                                 0,
9540                                 &written,
9541                                 splice_status,
9542                                 NULL);
9543
9544         if (!NT_STATUS_IS_OK(status)) {
9545                 d_printf("cli_splice failed: %s\n", nt_errstr(status));
9546                 goto out;
9547         }
9548
9549         /* Clear the old buffer. */
9550         memset(buf, '\0', file_size);
9551
9552         /* Read the new file. */
9553         status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
9554         if (!NT_STATUS_IS_OK(status)) {
9555                 d_printf("cli_read failed: %s\n", nt_errstr(status));
9556                 goto out;
9557         }
9558         if (nread != splice_size) {
9559                 d_printf("bad read of 0x%x, should be 0x%x\n",
9560                         (unsigned int)nread,
9561                         (unsigned int)splice_size);
9562                 goto out;
9563         }
9564
9565         /* MD5 the first 1MB + 713 bytes. */
9566         MD5Init(&md5_ctx);
9567         MD5Update(&md5_ctx, buf, splice_size);
9568         MD5Final(digest2, &md5_ctx);
9569
9570         /* Must be the same. */
9571         if (memcmp(digest1, digest2, 16) != 0) {
9572                 d_printf("bad MD5 compare\n");
9573                 goto out;
9574         }
9575
9576         correct = true;
9577         printf("Success on cli_splice test\n");
9578
9579   out:
9580
9581         if (cli1) {
9582                 if (fnum1 != UINT16_MAX) {
9583                         cli_close(cli1, fnum1);
9584                 }
9585                 if (fnum2 != UINT16_MAX) {
9586                         cli_close(cli1, fnum2);
9587                 }
9588
9589                 cli_unlink(cli1, fname_src,
9590                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9591                 cli_unlink(cli1, fname_dst,
9592                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9593
9594                 if (!torture_close_connection(cli1)) {
9595                         correct = false;
9596                 }
9597         }
9598
9599         TALLOC_FREE(frame);
9600         return correct;
9601 }
9602
9603 static bool run_uid_regression_test(int dummy)
9604 {
9605         static struct cli_state *cli;
9606         int16_t old_vuid;
9607         int32_t old_cnum;
9608         bool correct = True;
9609         struct smbXcli_tcon *orig_tcon = NULL;
9610         NTSTATUS status;
9611
9612         printf("starting uid regression test\n");
9613
9614         if (!torture_open_connection(&cli, 0)) {
9615                 return False;
9616         }
9617
9618         smbXcli_conn_set_sockopt(cli->conn, sockops);
9619
9620         /* Ok - now save then logoff our current user. */
9621         old_vuid = cli_state_get_uid(cli);
9622
9623         status = cli_ulogoff(cli);
9624         if (!NT_STATUS_IS_OK(status)) {
9625                 d_printf("(%s) cli_ulogoff failed: %s\n",
9626                          __location__, nt_errstr(status));
9627                 correct = false;
9628                 goto out;
9629         }
9630
9631         cli_state_set_uid(cli, old_vuid);
9632
9633         /* Try an operation. */
9634         status = cli_mkdir(cli, "\\uid_reg_test");
9635         if (NT_STATUS_IS_OK(status)) {
9636                 d_printf("(%s) cli_mkdir succeeded\n",
9637                          __location__);
9638                 correct = false;
9639                 goto out;
9640         } else {
9641                 /* Should be bad uid. */
9642                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
9643                                  NT_STATUS_USER_SESSION_DELETED)) {
9644                         correct = false;
9645                         goto out;
9646                 }
9647         }
9648
9649         old_cnum = cli_state_get_tid(cli);
9650         orig_tcon = cli_state_save_tcon(cli);
9651         if (orig_tcon == NULL) {
9652                 correct = false;
9653                 goto out;
9654         }
9655
9656         /* Now try a SMBtdis with the invalid vuid set to zero. */
9657         cli_state_set_uid(cli, 0);
9658
9659         /* This should succeed. */
9660         status = cli_tdis(cli);
9661
9662         if (NT_STATUS_IS_OK(status)) {
9663                 d_printf("First tdis with invalid vuid should succeed.\n");
9664         } else {
9665                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
9666                 correct = false;
9667                 cli_state_restore_tcon(cli, orig_tcon);
9668                 goto out;
9669         }
9670
9671         cli_state_restore_tcon(cli, orig_tcon);
9672         cli_state_set_uid(cli, old_vuid);
9673         cli_state_set_tid(cli, old_cnum);
9674
9675         /* This should fail. */
9676         status = cli_tdis(cli);
9677         if (NT_STATUS_IS_OK(status)) {
9678                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
9679                 correct = false;
9680                 goto out;
9681         } else {
9682                 /* Should be bad tid. */
9683                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
9684                                 NT_STATUS_NETWORK_NAME_DELETED)) {
9685                         correct = false;
9686                         goto out;
9687                 }
9688         }
9689
9690         cli_rmdir(cli, "\\uid_reg_test");
9691
9692   out:
9693
9694         cli_shutdown(cli);
9695         return correct;
9696 }
9697
9698
9699 static const char *illegal_chars = "*\\/?<>|\":";
9700 static char force_shortname_chars[] = " +,.[];=\177";
9701
9702 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
9703                              const char *mask, void *state)
9704 {
9705         struct cli_state *pcli = (struct cli_state *)state;
9706         fstring fname;
9707         NTSTATUS status = NT_STATUS_OK;
9708
9709         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
9710
9711         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9712                 return NT_STATUS_OK;
9713
9714         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
9715                 status = cli_rmdir(pcli, fname);
9716                 if (!NT_STATUS_IS_OK(status)) {
9717                         printf("del_fn: failed to rmdir %s\n,", fname );
9718                 }
9719         } else {
9720                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9721                 if (!NT_STATUS_IS_OK(status)) {
9722                         printf("del_fn: failed to unlink %s\n,", fname );
9723                 }
9724         }
9725         return status;
9726 }
9727
9728 struct sn_state {
9729         int matched;
9730         int i;
9731         bool val;
9732 };
9733
9734 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
9735                               const char *name, void *state)
9736 {
9737         struct sn_state *s = (struct sn_state  *)state;
9738         int i = s->i;
9739
9740 #if 0
9741         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
9742                 i, finfo->name, finfo->short_name);
9743 #endif
9744
9745         if (strchr(force_shortname_chars, i)) {
9746                 if (!finfo->short_name) {
9747                         /* Shortname not created when it should be. */
9748                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
9749                                 __location__, finfo->name, i);
9750                         s->val = true;
9751                 }
9752         } else if (finfo->short_name){
9753                 /* Shortname created when it should not be. */
9754                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
9755                         __location__, finfo->short_name, finfo->name);
9756                 s->val = true;
9757         }
9758         s->matched += 1;
9759         return NT_STATUS_OK;
9760 }
9761
9762 static bool run_shortname_test(int dummy)
9763 {
9764         static struct cli_state *cli;
9765         bool correct = True;
9766         int i;
9767         struct sn_state s;
9768         char fname[40];
9769         NTSTATUS status;
9770
9771         printf("starting shortname test\n");
9772
9773         if (!torture_open_connection(&cli, 0)) {
9774                 return False;
9775         }
9776
9777         smbXcli_conn_set_sockopt(cli->conn, sockops);
9778
9779         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9780         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9781         cli_rmdir(cli, "\\shortname");
9782
9783         status = cli_mkdir(cli, "\\shortname");
9784         if (!NT_STATUS_IS_OK(status)) {
9785                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
9786                         __location__, nt_errstr(status));
9787                 correct = false;
9788                 goto out;
9789         }
9790
9791         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
9792                 correct = false;
9793                 goto out;
9794         }
9795         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
9796                 correct = false;
9797                 goto out;
9798         }
9799
9800         s.val = false;
9801
9802         for (i = 32; i < 128; i++) {
9803                 uint16_t fnum = (uint16_t)-1;
9804
9805                 s.i = i;
9806
9807                 if (strchr(illegal_chars, i)) {
9808                         continue;
9809                 }
9810                 fname[15] = i;
9811
9812                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
9813                                    FILE_SHARE_READ|FILE_SHARE_WRITE,
9814                                    FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
9815                 if (!NT_STATUS_IS_OK(status)) {
9816                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
9817                                 __location__, fname, nt_errstr(status));
9818                         correct = false;
9819                         goto out;
9820                 }
9821                 cli_close(cli, fnum);
9822
9823                 s.matched = 0;
9824                 status = cli_list(cli, "\\shortname\\test*.*", 0,
9825                                   shortname_list_fn, &s);
9826                 if (s.matched != 1) {
9827                         d_printf("(%s) failed to list %s: %s\n",
9828                                 __location__, fname, nt_errstr(status));
9829                         correct = false;
9830                         goto out;
9831                 }
9832
9833                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9834                 if (!NT_STATUS_IS_OK(status)) {
9835                         d_printf("(%s) failed to delete %s: %s\n",
9836                                 __location__, fname, nt_errstr(status));
9837                         correct = false;
9838                         goto out;
9839                 }
9840
9841                 if (s.val) {
9842                         correct = false;
9843                         goto out;
9844                 }
9845         }
9846
9847   out:
9848
9849         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
9850         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
9851         cli_rmdir(cli, "\\shortname");
9852         torture_close_connection(cli);
9853         return correct;
9854 }
9855
9856 static void pagedsearch_cb(struct tevent_req *req)
9857 {
9858         TLDAPRC rc;
9859         struct tldap_message *msg;
9860         char *dn;
9861
9862         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
9863         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9864                 d_printf("tldap_search_paged_recv failed: %s\n",
9865                          tldap_rc2string(rc));
9866                 return;
9867         }
9868         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
9869                 TALLOC_FREE(msg);
9870                 return;
9871         }
9872         if (!tldap_entry_dn(msg, &dn)) {
9873                 d_printf("tldap_entry_dn failed\n");
9874                 return;
9875         }
9876         d_printf("%s\n", dn);
9877         TALLOC_FREE(msg);
9878 }
9879
9880 static bool run_tldap(int dummy)
9881 {
9882         struct tldap_context *ld;
9883         int fd;
9884         TLDAPRC rc;
9885         NTSTATUS status;
9886         struct sockaddr_storage addr;
9887         struct tevent_context *ev;
9888         struct tevent_req *req;
9889         char *basedn;
9890         const char *filter;
9891
9892         if (!resolve_name(host, &addr, 0, false)) {
9893                 d_printf("could not find host %s\n", host);
9894                 return false;
9895         }
9896         status = open_socket_out(&addr, 389, 9999, &fd);
9897         if (!NT_STATUS_IS_OK(status)) {
9898                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
9899                 return false;
9900         }
9901
9902         ld = tldap_context_create(talloc_tos(), fd);
9903         if (ld == NULL) {
9904                 close(fd);
9905                 d_printf("tldap_context_create failed\n");
9906                 return false;
9907         }
9908
9909         rc = tldap_fetch_rootdse(ld);
9910         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9911                 d_printf("tldap_fetch_rootdse failed: %s\n",
9912                          tldap_errstr(talloc_tos(), ld, rc));
9913                 return false;
9914         }
9915
9916         basedn = tldap_talloc_single_attribute(
9917                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
9918         if (basedn == NULL) {
9919                 d_printf("no defaultNamingContext\n");
9920                 return false;
9921         }
9922         d_printf("defaultNamingContext: %s\n", basedn);
9923
9924         ev = samba_tevent_context_init(talloc_tos());
9925         if (ev == NULL) {
9926                 d_printf("tevent_context_init failed\n");
9927                 return false;
9928         }
9929
9930         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
9931                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
9932                                       NULL, 0, 0,
9933                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
9934         if (req == NULL) {
9935                 d_printf("tldap_search_paged_send failed\n");
9936                 return false;
9937         }
9938         tevent_req_set_callback(req, pagedsearch_cb, NULL);
9939
9940         tevent_req_poll(req, ev);
9941
9942         TALLOC_FREE(req);
9943
9944         /* test search filters against rootDSE */
9945         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
9946                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
9947
9948         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
9949                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
9950                           talloc_tos(), NULL);
9951         if (!TLDAP_RC_IS_SUCCESS(rc)) {
9952                 d_printf("tldap_search with complex filter failed: %s\n",
9953                          tldap_errstr(talloc_tos(), ld, rc));
9954                 return false;
9955         }
9956
9957         TALLOC_FREE(ld);
9958         return true;
9959 }
9960
9961 /* Torture test to ensure no regression of :
9962 https://bugzilla.samba.org/show_bug.cgi?id=7084
9963 */
9964
9965 static bool run_dir_createtime(int dummy)
9966 {
9967         struct cli_state *cli;
9968         const char *dname = "\\testdir_createtime";
9969         const char *fname = "\\testdir_createtime\\testfile";
9970         NTSTATUS status;
9971         struct timespec create_time;
9972         struct timespec create_time1;
9973         uint16_t fnum;
9974         bool ret = false;
9975
9976         if (!torture_open_connection(&cli, 0)) {
9977                 return false;
9978         }
9979
9980         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9981         cli_rmdir(cli, dname);
9982
9983         status = cli_mkdir(cli, dname);
9984         if (!NT_STATUS_IS_OK(status)) {
9985                 printf("mkdir failed: %s\n", nt_errstr(status));
9986                 goto out;
9987         }
9988
9989         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
9990                                 NULL, NULL, NULL);
9991         if (!NT_STATUS_IS_OK(status)) {
9992                 printf("cli_qpathinfo2 returned %s\n",
9993                        nt_errstr(status));
9994                 goto out;
9995         }
9996
9997         /* Sleep 3 seconds, then create a file. */
9998         sleep(3);
9999
10000         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
10001                          DENY_NONE, &fnum);
10002         if (!NT_STATUS_IS_OK(status)) {
10003                 printf("cli_openx failed: %s\n", nt_errstr(status));
10004                 goto out;
10005         }
10006
10007         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
10008                                 NULL, NULL, NULL);
10009         if (!NT_STATUS_IS_OK(status)) {
10010                 printf("cli_qpathinfo2 (2) returned %s\n",
10011                        nt_errstr(status));
10012                 goto out;
10013         }
10014
10015         if (timespec_compare(&create_time1, &create_time)) {
10016                 printf("run_dir_createtime: create time was updated (error)\n");
10017         } else {
10018                 printf("run_dir_createtime: create time was not updated (correct)\n");
10019                 ret = true;
10020         }
10021
10022   out:
10023
10024         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10025         cli_rmdir(cli, dname);
10026         if (!torture_close_connection(cli)) {
10027                 ret = false;
10028         }
10029         return ret;
10030 }
10031
10032
10033 static bool run_streamerror(int dummy)
10034 {
10035         struct cli_state *cli;
10036         const char *dname = "\\testdir_streamerror";
10037         const char *streamname =
10038                 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
10039         NTSTATUS status;
10040         time_t change_time, access_time, write_time;
10041         off_t size;
10042         uint16_t mode, fnum;
10043         bool ret = true;
10044
10045         if (!torture_open_connection(&cli, 0)) {
10046                 return false;
10047         }
10048
10049         cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10050         cli_rmdir(cli, dname);
10051
10052         status = cli_mkdir(cli, dname);
10053         if (!NT_STATUS_IS_OK(status)) {
10054                 printf("mkdir failed: %s\n", nt_errstr(status));
10055                 return false;
10056         }
10057
10058         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
10059                                 &write_time, &size, &mode);
10060         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
10061                 printf("pathinfo returned %s, expected "
10062                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
10063                        nt_errstr(status));
10064                 ret = false;
10065         }
10066
10067         status = cli_ntcreate(cli, streamname, 0x16,
10068                               FILE_READ_DATA|FILE_READ_EA|
10069                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
10070                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
10071                               FILE_OPEN, 0, 0, &fnum, NULL);
10072
10073         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
10074                 printf("ntcreate returned %s, expected "
10075                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
10076                        nt_errstr(status));
10077                 ret = false;
10078         }
10079
10080
10081         cli_rmdir(cli, dname);
10082         return ret;
10083 }
10084
10085 struct pidtest_state {
10086         bool success;
10087         uint16_t vwv[1];
10088         DATA_BLOB data;
10089 };
10090
10091 static void pid_echo_done(struct tevent_req *subreq);
10092
10093 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
10094                         struct tevent_context *ev,
10095                         struct cli_state *cli)
10096 {
10097         struct tevent_req *req, *subreq;
10098         struct pidtest_state *state;
10099
10100         req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
10101         if (req == NULL) {
10102                 return NULL;
10103         }
10104
10105         SSVAL(state->vwv, 0, 1);
10106         state->data = data_blob_const("hello", 5);
10107
10108         subreq = smb1cli_req_send(state,
10109                                 ev,
10110                                 cli->conn,
10111                                 SMBecho,
10112                                 0, 0, /* *_flags */
10113                                 0, 0, /* *_flags2 */
10114                                 cli->timeout,
10115                                 0xDEADBEEF, /* pid */
10116                                 NULL, /* tcon */
10117                                 NULL, /* session */
10118                                 ARRAY_SIZE(state->vwv), state->vwv,
10119                                 state->data.length, state->data.data);
10120
10121         if (tevent_req_nomem(subreq, req)) {
10122                 return tevent_req_post(req, ev);
10123         }
10124         tevent_req_set_callback(subreq, pid_echo_done, req);
10125         return req;
10126 }
10127
10128 static void pid_echo_done(struct tevent_req *subreq)
10129 {
10130         struct tevent_req *req = tevent_req_callback_data(
10131                 subreq, struct tevent_req);
10132         struct pidtest_state *state = tevent_req_data(
10133                 req, struct pidtest_state);
10134         NTSTATUS status;
10135         uint32_t num_bytes;
10136         uint8_t *bytes = NULL;
10137         struct iovec *recv_iov = NULL;
10138         uint8_t *phdr = NULL;
10139         uint16_t pidlow = 0;
10140         uint16_t pidhigh = 0;
10141         struct smb1cli_req_expected_response expected[] = {
10142         {
10143                 .status = NT_STATUS_OK,
10144                 .wct    = 1,
10145         },
10146         };
10147
10148         status = smb1cli_req_recv(subreq, state,
10149                                 &recv_iov,
10150                                 &phdr,
10151                                 NULL, /* pwct */
10152                                 NULL, /* pvwv */
10153                                 NULL, /* pvwv_offset */
10154                                 &num_bytes,
10155                                 &bytes,
10156                                 NULL, /* pbytes_offset */
10157                                 NULL, /* pinbuf */
10158                                 expected, ARRAY_SIZE(expected));
10159
10160         TALLOC_FREE(subreq);
10161
10162         if (!NT_STATUS_IS_OK(status)) {
10163                 tevent_req_nterror(req, status);
10164                 return;
10165         }
10166
10167         if (num_bytes != state->data.length) {
10168                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10169                 return;
10170         }
10171
10172         if (memcmp(bytes, state->data.data, num_bytes) != 0) {
10173                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10174                 return;
10175         }
10176
10177         /* Check pid low/high == DEADBEEF */
10178         pidlow = SVAL(phdr, HDR_PID);
10179         if (pidlow != 0xBEEF){
10180                 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
10181                         (unsigned int)pidlow);
10182                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10183                 return;
10184         }
10185         pidhigh = SVAL(phdr, HDR_PIDHIGH);
10186         if (pidhigh != 0xDEAD){
10187                 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
10188                         (unsigned int)pidhigh);
10189                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
10190                 return;
10191         }
10192
10193         tevent_req_done(req);
10194 }
10195
10196 static NTSTATUS pid_echo_recv(struct tevent_req *req)
10197 {
10198         return tevent_req_simple_recv_ntstatus(req);
10199 }
10200
10201 static bool run_pidhigh(int dummy)
10202 {
10203         bool success = false;
10204         struct cli_state *cli = NULL;
10205         NTSTATUS status;
10206         struct tevent_context *ev = NULL;
10207         struct tevent_req *req = NULL;
10208         TALLOC_CTX *frame = talloc_stackframe();
10209
10210         printf("starting pid high test\n");
10211         if (!torture_open_connection(&cli, 0)) {
10212                 return false;
10213         }
10214         smbXcli_conn_set_sockopt(cli->conn, sockops);
10215
10216         ev = samba_tevent_context_init(frame);
10217         if (ev == NULL) {
10218                 goto fail;
10219         }
10220
10221         req = pid_echo_send(frame, ev, cli);
10222         if (req == NULL) {
10223                 goto fail;
10224         }
10225
10226         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
10227                 goto fail;
10228         }
10229
10230         status = pid_echo_recv(req);
10231         if (NT_STATUS_IS_OK(status)) {
10232                 printf("pid high test ok\n");
10233                 success = true;
10234         }
10235
10236  fail:
10237
10238         TALLOC_FREE(frame);
10239         torture_close_connection(cli);
10240         return success;
10241 }
10242
10243 /*
10244   Test Windows open on a bad POSIX symlink.
10245  */
10246 static bool run_symlink_open_test(int dummy)
10247 {
10248         static struct cli_state *cli;
10249         const char *fname = "non_existant_file";
10250         const char *sname = "dangling_symlink";
10251         uint16_t fnum = (uint16_t)-1;
10252         bool correct = false;
10253         NTSTATUS status;
10254         TALLOC_CTX *frame = NULL;
10255
10256         frame = talloc_stackframe();
10257
10258         printf("Starting Windows bad symlink open test\n");
10259
10260         if (!torture_open_connection(&cli, 0)) {
10261                 TALLOC_FREE(frame);
10262                 return false;
10263         }
10264
10265         smbXcli_conn_set_sockopt(cli->conn, sockops);
10266
10267         status = torture_setup_unix_extensions(cli);
10268         if (!NT_STATUS_IS_OK(status)) {
10269                 TALLOC_FREE(frame);
10270                 return false;
10271         }
10272
10273         /* Ensure nothing exists. */
10274         cli_setatr(cli, fname, 0, 0);
10275         cli_posix_unlink(cli, fname);
10276         cli_setatr(cli, sname, 0, 0);
10277         cli_posix_unlink(cli, sname);
10278
10279         /* Create a symlink pointing nowhere. */
10280         status = cli_posix_symlink(cli, fname, sname);
10281         if (!NT_STATUS_IS_OK(status)) {
10282                 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
10283                         sname,
10284                         fname,
10285                         nt_errstr(status));
10286                 goto out;
10287         }
10288
10289         /* Now ensure that a Windows open doesn't hang. */
10290         status = cli_ntcreate(cli,
10291                         sname,
10292                         0,
10293                         FILE_READ_DATA|FILE_WRITE_DATA,
10294                         0,
10295                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10296                         FILE_OPEN_IF,
10297                         0x0,
10298                         0x0,
10299                         &fnum,
10300                         NULL);
10301
10302         /*
10303          * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
10304          * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
10305          * we use O_NOFOLLOW on the server or not.
10306          */
10307         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
10308             NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
10309         {
10310                 correct = true;
10311         } else {
10312                 printf("cli_ntcreate of %s returned %s - should return"
10313                                 " either (%s) or (%s)\n",
10314                         sname,
10315                         nt_errstr(status),
10316                         nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
10317                         nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
10318                 goto out;
10319         }
10320
10321         correct = true;
10322
10323   out:
10324
10325         if (fnum != (uint16_t)-1) {
10326                 cli_close(cli, fnum);
10327                 fnum = (uint16_t)-1;
10328         }
10329
10330         cli_setatr(cli, sname, 0, 0);
10331         cli_posix_unlink(cli, sname);
10332         cli_setatr(cli, fname, 0, 0);
10333         cli_posix_unlink(cli, fname);
10334
10335         if (!torture_close_connection(cli)) {
10336                 correct = false;
10337         }
10338
10339         TALLOC_FREE(frame);
10340         return correct;
10341 }
10342
10343 /*
10344  * Only testing minimal time strings, as the others
10345  * need (locale-dependent) guessing at what strftime does and
10346  * even may differ in builds.
10347  */
10348 static bool timesubst_test(void)
10349 {
10350         TALLOC_CTX *ctx = NULL;
10351         /* Sa 23. Dez 04:33:20 CET 2017 */
10352         const struct timeval tv = { 1514000000, 123 };
10353         const char* expect_minimal = "20171223_033320";
10354         const char* expect_minus   = "20171223_033320_000123";
10355         char *s;
10356         char *env_tz, *orig_tz = NULL;
10357         bool result = true;
10358
10359         ctx = talloc_new(NULL);
10360
10361         env_tz = getenv("TZ");
10362         if(env_tz) {
10363                 orig_tz = talloc_strdup(ctx, env_tz);
10364         }
10365         setenv("TZ", "UTC", 1);
10366
10367         s = minimal_timeval_string(ctx, &tv, false);
10368
10369         if(!s || strcmp(s, expect_minimal)) {
10370                 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
10371                        "[%s]\n", s ? s : "<nil>", expect_minimal);
10372                 result = false;
10373         }
10374         TALLOC_FREE(s);
10375         s = minimal_timeval_string(ctx, &tv, true);
10376         if(!s || strcmp(s, expect_minus)) {
10377                 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
10378                        "[%s]\n", s ? s : "<nil>", expect_minus);
10379                 result = false;
10380         }
10381         TALLOC_FREE(s);
10382
10383         if(orig_tz) {
10384                 setenv("TZ", orig_tz, 1);
10385         }
10386
10387         TALLOC_FREE(ctx);
10388         return result;
10389 }
10390
10391 static bool run_local_substitute(int dummy)
10392 {
10393         bool ok = true;
10394
10395         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
10396         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
10397         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
10398         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
10399         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
10400         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
10401         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
10402         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
10403         ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
10404         /* Substitution depends on current time, so better test the underlying
10405            formatting function. At least covers %t. */
10406         ok &= timesubst_test();
10407
10408         /* Different captialization rules in sub_basic... */
10409
10410         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
10411                        "blaDOM") == 0);
10412
10413         return ok;
10414 }
10415
10416 static bool run_local_base64(int dummy)
10417 {
10418         int i;
10419         bool ret = true;
10420
10421         for (i=1; i<2000; i++) {
10422                 DATA_BLOB blob1, blob2;
10423                 char *b64;
10424
10425                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
10426                 blob1.length = i;
10427                 generate_random_buffer(blob1.data, blob1.length);
10428
10429                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
10430                 if (b64 == NULL) {
10431                         d_fprintf(stderr, "base64_encode_data_blob failed "
10432                                   "for %d bytes\n", i);
10433                         ret = false;
10434                 }
10435                 blob2 = base64_decode_data_blob(b64);
10436                 TALLOC_FREE(b64);
10437
10438                 if (data_blob_cmp(&blob1, &blob2)) {
10439                         d_fprintf(stderr, "data_blob_cmp failed for %d "
10440                                   "bytes\n", i);
10441                         ret = false;
10442                 }
10443                 TALLOC_FREE(blob1.data);
10444                 data_blob_free(&blob2);
10445         }
10446         return ret;
10447 }
10448
10449 static void parse_fn(const struct gencache_timeout *t,
10450                      DATA_BLOB blob,
10451                      void *private_data)
10452 {
10453         return;
10454 }
10455
10456 static bool run_local_gencache(int dummy)
10457 {
10458         char *val;
10459         time_t tm;
10460         DATA_BLOB blob;
10461         char v;
10462         struct memcache *mem;
10463         int i;
10464
10465         mem = memcache_init(NULL, 0);
10466         if (mem == NULL) {
10467                 d_printf("%s: memcache_init failed\n", __location__);
10468                 return false;
10469         }
10470         memcache_set_global(mem);
10471
10472         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
10473                 d_printf("%s: gencache_set() failed\n", __location__);
10474                 return False;
10475         }
10476
10477         if (!gencache_get("foo", NULL, NULL, NULL)) {
10478                 d_printf("%s: gencache_get() failed\n", __location__);
10479                 return False;
10480         }
10481
10482         for (i=0; i<1000000; i++) {
10483                 gencache_parse("foo", parse_fn, NULL);
10484         }
10485
10486         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10487                 d_printf("%s: gencache_get() failed\n", __location__);
10488                 return False;
10489         }
10490         TALLOC_FREE(val);
10491
10492         if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
10493                 d_printf("%s: gencache_get() failed\n", __location__);
10494                 return False;
10495         }
10496
10497         if (strcmp(val, "bar") != 0) {
10498                 d_printf("%s: gencache_get() returned %s, expected %s\n",
10499                          __location__, val, "bar");
10500                 TALLOC_FREE(val);
10501                 return False;
10502         }
10503
10504         TALLOC_FREE(val);
10505
10506         if (!gencache_del("foo")) {
10507                 d_printf("%s: gencache_del() failed\n", __location__);
10508                 return False;
10509         }
10510         if (gencache_del("foo")) {
10511                 d_printf("%s: second gencache_del() succeeded\n",
10512                          __location__);
10513                 return False;
10514         }
10515
10516         if (gencache_get("foo", talloc_tos(), &val, &tm)) {
10517                 d_printf("%s: gencache_get() on deleted entry "
10518                          "succeeded\n", __location__);
10519                 return False;
10520         }
10521
10522         blob = data_blob_string_const_null("bar");
10523         tm = time(NULL) + 60;
10524
10525         if (!gencache_set_data_blob("foo", blob, tm)) {
10526                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
10527                 return False;
10528         }
10529
10530         if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10531                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
10532                 return False;
10533         }
10534
10535         if (strcmp((const char *)blob.data, "bar") != 0) {
10536                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
10537                          __location__, (const char *)blob.data, "bar");
10538                 data_blob_free(&blob);
10539                 return False;
10540         }
10541
10542         data_blob_free(&blob);
10543
10544         if (!gencache_del("foo")) {
10545                 d_printf("%s: gencache_del() failed\n", __location__);
10546                 return False;
10547         }
10548         if (gencache_del("foo")) {
10549                 d_printf("%s: second gencache_del() succeeded\n",
10550                          __location__);
10551                 return False;
10552         }
10553
10554         if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
10555                 d_printf("%s: gencache_get_data_blob() on deleted entry "
10556                          "succeeded\n", __location__);
10557                 return False;
10558         }
10559
10560         v = 1;
10561         blob.data = (uint8_t *)&v;
10562         blob.length = sizeof(v);
10563
10564         if (!gencache_set_data_blob("blob", blob, tm)) {
10565                 d_printf("%s: gencache_set_data_blob() failed\n",
10566                          __location__);
10567                 return false;
10568         }
10569         if (gencache_get("blob", talloc_tos(), &val, &tm)) {
10570                 d_printf("%s: gencache_get succeeded\n", __location__);
10571                 return false;
10572         }
10573
10574         return True;
10575 }
10576
10577 static bool rbt_testval(struct db_context *db, const char *key,
10578                         const char *value)
10579 {
10580         struct db_record *rec;
10581         TDB_DATA data = string_tdb_data(value);
10582         bool ret = false;
10583         NTSTATUS status;
10584         TDB_DATA dbvalue;
10585
10586         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10587         if (rec == NULL) {
10588                 d_fprintf(stderr, "fetch_locked failed\n");
10589                 goto done;
10590         }
10591         status = dbwrap_record_store(rec, data, 0);
10592         if (!NT_STATUS_IS_OK(status)) {
10593                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
10594                 goto done;
10595         }
10596         TALLOC_FREE(rec);
10597
10598         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
10599         if (rec == NULL) {
10600                 d_fprintf(stderr, "second fetch_locked failed\n");
10601                 goto done;
10602         }
10603
10604         dbvalue = dbwrap_record_get_value(rec);
10605         if ((dbvalue.dsize != data.dsize)
10606             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
10607                 d_fprintf(stderr, "Got wrong data back\n");
10608                 goto done;
10609         }
10610
10611         ret = true;
10612  done:
10613         TALLOC_FREE(rec);
10614         return ret;
10615 }
10616
10617 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
10618 {
10619         int *count2 = (int *)private_data;
10620         (*count2)++;
10621         return 0;
10622 }
10623
10624 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
10625 {
10626         int *count2 = (int *)private_data;
10627         (*count2)++;
10628         dbwrap_record_delete(rec);
10629         return 0;
10630 }
10631
10632 static bool run_local_rbtree(int dummy)
10633 {
10634         struct db_context *db;
10635         bool ret = false;
10636         int i;
10637         NTSTATUS status;
10638         int count = 0;
10639         int count2 = 0;
10640
10641         db = db_open_rbt(NULL);
10642
10643         if (db == NULL) {
10644                 d_fprintf(stderr, "db_open_rbt failed\n");
10645                 return false;
10646         }
10647
10648         for (i=0; i<1000; i++) {
10649                 char *key, *value;
10650
10651                 if (asprintf(&key, "key%ld", random()) == -1) {
10652                         goto done;
10653                 }
10654                 if (asprintf(&value, "value%ld", random()) == -1) {
10655                         SAFE_FREE(key);
10656                         goto done;
10657                 }
10658
10659                 if (!rbt_testval(db, key, value)) {
10660                         SAFE_FREE(key);
10661                         SAFE_FREE(value);
10662                         goto done;
10663                 }
10664
10665                 SAFE_FREE(value);
10666                 if (asprintf(&value, "value%ld", random()) == -1) {
10667                         SAFE_FREE(key);
10668                         goto done;
10669                 }
10670
10671                 if (!rbt_testval(db, key, value)) {
10672                         SAFE_FREE(key);
10673                         SAFE_FREE(value);
10674                         goto done;
10675                 }
10676
10677                 SAFE_FREE(key);
10678                 SAFE_FREE(value);
10679         }
10680
10681         ret = true;
10682         count = 0; count2 = 0;
10683         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10684                                       &count2, &count);
10685         printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10686         if ((count != count2) || (count != 1000)) {
10687                 ret = false;
10688         }
10689         count = 0; count2 = 0;
10690         status = dbwrap_traverse(db, local_rbtree_traverse_delete,
10691                                  &count2, &count);
10692         printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10693         if ((count != count2) || (count != 1000)) {
10694                 ret = false;
10695         }
10696         count = 0; count2 = 0;
10697         status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
10698                                       &count2, &count);
10699         printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
10700         if ((count != count2) || (count != 0)) {
10701                 ret = false;
10702         }
10703
10704  done:
10705         TALLOC_FREE(db);
10706         return ret;
10707 }
10708
10709
10710 /*
10711   local test for character set functions
10712
10713   This is a very simple test for the functionality in convert_string_error()
10714  */
10715 static bool run_local_convert_string(int dummy)
10716 {
10717         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
10718         const char *test_strings[2] = { "March", "M\303\244rz" };
10719         char dst[7];
10720         int i;
10721
10722         for (i=0; i<2; i++) {
10723                 const char *str = test_strings[i];
10724                 int len = strlen(str);
10725                 size_t converted_size;
10726                 bool ret;
10727
10728                 memset(dst, 'X', sizeof(dst));
10729
10730                 /* first try with real source length */
10731                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10732                                            str, len,
10733                                            dst, sizeof(dst),
10734                                            &converted_size);
10735                 if (ret != true) {
10736                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10737                         goto failed;
10738                 }
10739
10740                 if (converted_size != len) {
10741                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10742                                   str, len, (int)converted_size);
10743                         goto failed;
10744                 }
10745
10746                 if (strncmp(str, dst, converted_size) != 0) {
10747                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10748                         goto failed;
10749                 }
10750
10751                 if (strlen(str) != converted_size) {
10752                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10753                                   (int)strlen(str), (int)converted_size);
10754                         goto failed;
10755                 }
10756
10757                 if (dst[converted_size] != 'X') {
10758                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10759                         goto failed;
10760                 }
10761
10762                 /* now with srclen==-1, this causes the nul to be
10763                  * converted too */
10764                 ret = convert_string_error(CH_UNIX, CH_UTF8,
10765                                            str, -1,
10766                                            dst, sizeof(dst),
10767                                            &converted_size);
10768                 if (ret != true) {
10769                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
10770                         goto failed;
10771                 }
10772
10773                 if (converted_size != len+1) {
10774                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
10775                                   str, len, (int)converted_size);
10776                         goto failed;
10777                 }
10778
10779                 if (strncmp(str, dst, converted_size) != 0) {
10780                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
10781                         goto failed;
10782                 }
10783
10784                 if (len+1 != converted_size) {
10785                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
10786                                   len+1, (int)converted_size);
10787                         goto failed;
10788                 }
10789
10790                 if (dst[converted_size] != 'X') {
10791                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
10792                         goto failed;
10793                 }
10794
10795         }
10796
10797
10798         TALLOC_FREE(tmp_ctx);
10799         return true;
10800 failed:
10801         TALLOC_FREE(tmp_ctx);
10802         return false;
10803 }
10804
10805 static bool run_local_string_to_sid(int dummy) {
10806         struct dom_sid sid;
10807
10808         if (string_to_sid(&sid, "S--1-5-32-545")) {
10809                 printf("allowing S--1-5-32-545\n");
10810                 return false;
10811         }
10812         if (string_to_sid(&sid, "S-1-5-32-+545")) {
10813                 printf("allowing S-1-5-32-+545\n");
10814                 return false;
10815         }
10816         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")) {
10817                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
10818                 return false;
10819         }
10820         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
10821                 printf("allowing S-1-5-32-545-abc\n");
10822                 return false;
10823         }
10824         if (string_to_sid(&sid, "S-300-5-32-545")) {
10825                 printf("allowing S-300-5-32-545\n");
10826                 return false;
10827         }
10828         if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
10829                 printf("allowing S-1-0xfffffffffffffe-32-545\n");
10830                 return false;
10831         }
10832         if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
10833                 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
10834                 return false;
10835         }
10836         if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
10837                 printf("could not parse S-1-0xfffffffffffe-32-545\n");
10838                 return false;
10839         }
10840         if (!string_to_sid(&sid, "S-1-5-32-545")) {
10841                 printf("could not parse S-1-5-32-545\n");
10842                 return false;
10843         }
10844         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
10845                 struct dom_sid_buf buf;
10846                 printf("mis-parsed S-1-5-32-545 as %s\n",
10847                        dom_sid_str_buf(&sid, &buf));
10848                 return false;
10849         }
10850         return true;
10851 }
10852
10853 static bool sid_to_string_test(const char *expected) {
10854         char *str;
10855         bool res = true;
10856         struct dom_sid sid;
10857
10858         if (!string_to_sid(&sid, expected)) {
10859                 printf("could not parse %s\n", expected);
10860                 return false;
10861         }
10862
10863         str = dom_sid_string(NULL, &sid);
10864         if (strcmp(str, expected)) {
10865                 printf("Comparison failed (%s != %s)\n", str, expected);
10866                 res = false;
10867         }
10868         TALLOC_FREE(str);
10869         return res;
10870 }
10871
10872 static bool run_local_sid_to_string(int dummy) {
10873         if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
10874                 return false;
10875         if (!sid_to_string_test("S-1-545"))
10876                 return false;
10877         if (!sid_to_string_test("S-255-3840-1-1-1-1"))
10878                 return false;
10879         return true;
10880 }
10881
10882 static bool run_local_binary_to_sid(int dummy) {
10883         ssize_t ret;
10884         struct dom_sid *sid = talloc(NULL, struct dom_sid);
10885         static const uint8_t good_binary_sid[] = {
10886                 0x1, /* revision number */
10887                 15, /* num auths */
10888                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10889                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10890                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10891                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10892                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10893                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10894                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10895                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10896                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10897                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10898                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10899                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10900                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10901                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10902                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10903                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10904         };
10905
10906         static const uint8_t long_binary_sid[] = {
10907                 0x1, /* revision number */
10908                 15, /* num auths */
10909                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10910                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10911                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10912                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10913                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10914                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10915                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10916                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10917                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10918                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10919                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10920                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10921                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10922                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10923                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10924                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10925                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10926                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10927                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10928         };
10929
10930         static const uint8_t long_binary_sid2[] = {
10931                 0x1, /* revision number */
10932                 32, /* num auths */
10933                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
10934                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
10935                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
10936                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
10937                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
10938                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
10939                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
10940                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
10941                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
10942                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
10943                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
10944                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
10945                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
10946                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
10947                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
10948                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
10949                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
10950                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
10951                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
10952                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
10953                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
10954                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
10955                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
10956                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
10957                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
10958                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
10959                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
10960                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
10961                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
10962                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
10963                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
10964                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
10965                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
10966         };
10967
10968         ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
10969         if (ret == -1) {
10970                 return false;
10971         }
10972         ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
10973         if (ret != -1) {
10974                 return false;
10975         }
10976         ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
10977         if (ret != -1) {
10978                 return false;
10979         }
10980         return true;
10981 }
10982
10983 /* Split a path name into filename and stream name components. Canonicalise
10984  * such that an implicit $DATA token is always explicit.
10985  *
10986  * The "specification" of this function can be found in the
10987  * run_local_stream_name() function in torture.c, I've tried those
10988  * combinations against a W2k3 server.
10989  */
10990
10991 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
10992                                        char **pbase, char **pstream)
10993 {
10994         char *base = NULL;
10995         char *stream = NULL;
10996         char *sname; /* stream name */
10997         const char *stype; /* stream type */
10998
10999         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
11000
11001         sname = strchr_m(fname, ':');
11002
11003         if (sname == NULL) {
11004                 if (pbase != NULL) {
11005                         base = talloc_strdup(mem_ctx, fname);
11006                         NT_STATUS_HAVE_NO_MEMORY(base);
11007                 }
11008                 goto done;
11009         }
11010
11011         if (pbase != NULL) {
11012                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
11013                 NT_STATUS_HAVE_NO_MEMORY(base);
11014         }
11015
11016         sname += 1;
11017
11018         stype = strchr_m(sname, ':');
11019
11020         if (stype == NULL) {
11021                 sname = talloc_strdup(mem_ctx, sname);
11022                 stype = "$DATA";
11023         }
11024         else {
11025                 if (strcasecmp_m(stype, ":$DATA") != 0) {
11026                         /*
11027                          * If there is an explicit stream type, so far we only
11028                          * allow $DATA. Is there anything else allowed? -- vl
11029                          */
11030                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
11031                         TALLOC_FREE(base);
11032                         return NT_STATUS_OBJECT_NAME_INVALID;
11033                 }
11034                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
11035                 stype += 1;
11036         }
11037
11038         if (sname == NULL) {
11039                 TALLOC_FREE(base);
11040                 return NT_STATUS_NO_MEMORY;
11041         }
11042
11043         if (sname[0] == '\0') {
11044                 /*
11045                  * no stream name, so no stream
11046                  */
11047                 goto done;
11048         }
11049
11050         if (pstream != NULL) {
11051                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
11052                 if (stream == NULL) {
11053                         TALLOC_FREE(sname);
11054                         TALLOC_FREE(base);
11055                         return NT_STATUS_NO_MEMORY;
11056                 }
11057                 /*
11058                  * upper-case the type field
11059                  */
11060                 (void)strupper_m(strchr_m(stream, ':')+1);
11061         }
11062
11063  done:
11064         if (pbase != NULL) {
11065                 *pbase = base;
11066         }
11067         if (pstream != NULL) {
11068                 *pstream = stream;
11069         }
11070         return NT_STATUS_OK;
11071 }
11072
11073 static bool test_stream_name(const char *fname, const char *expected_base,
11074                              const char *expected_stream,
11075                              NTSTATUS expected_status)
11076 {
11077         NTSTATUS status;
11078         char *base = NULL;
11079         char *stream = NULL;
11080
11081         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
11082         if (!NT_STATUS_EQUAL(status, expected_status)) {
11083                 goto error;
11084         }
11085
11086         if (!NT_STATUS_IS_OK(status)) {
11087                 return true;
11088         }
11089
11090         if (base == NULL) goto error;
11091
11092         if (strcmp(expected_base, base) != 0) goto error;
11093
11094         if ((expected_stream != NULL) && (stream == NULL)) goto error;
11095         if ((expected_stream == NULL) && (stream != NULL)) goto error;
11096
11097         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
11098                 goto error;
11099
11100         TALLOC_FREE(base);
11101         TALLOC_FREE(stream);
11102         return true;
11103
11104  error:
11105         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
11106                   fname, expected_base ? expected_base : "<NULL>",
11107                   expected_stream ? expected_stream : "<NULL>",
11108                   nt_errstr(expected_status));
11109         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
11110                   base ? base : "<NULL>", stream ? stream : "<NULL>",
11111                   nt_errstr(status));
11112         TALLOC_FREE(base);
11113         TALLOC_FREE(stream);
11114         return false;
11115 }
11116
11117 static bool run_local_stream_name(int dummy)
11118 {
11119         bool ret = true;
11120
11121         ret &= test_stream_name(
11122                 "bla", "bla", NULL, NT_STATUS_OK);
11123         ret &= test_stream_name(
11124                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
11125         ret &= test_stream_name(
11126                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
11127         ret &= test_stream_name(
11128                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
11129         ret &= test_stream_name(
11130                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
11131         ret &= test_stream_name(
11132                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
11133         ret &= test_stream_name(
11134                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
11135         ret &= test_stream_name(
11136                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
11137
11138         return ret;
11139 }
11140
11141 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
11142 {
11143         if (a.length != b.length) {
11144                 printf("a.length=%d != b.length=%d\n",
11145                        (int)a.length, (int)b.length);
11146                 return false;
11147         }
11148         if (memcmp(a.data, b.data, a.length) != 0) {
11149                 printf("a.data and b.data differ\n");
11150                 return false;
11151         }
11152         return true;
11153 }
11154
11155 static bool run_local_memcache(int dummy)
11156 {
11157         struct memcache *cache;
11158         DATA_BLOB k1, k2, k3;
11159         DATA_BLOB d1, d3;
11160         DATA_BLOB v1, v3;
11161
11162         TALLOC_CTX *mem_ctx;
11163         char *ptr1 = NULL;
11164         char *ptr2 = NULL;
11165
11166         char *str1, *str2;
11167         size_t size1, size2;
11168         bool ret = false;
11169
11170         mem_ctx = talloc_init("foo");
11171         if (mem_ctx == NULL) {
11172                 return false;
11173         }
11174
11175         /* STAT_CACHE TESTS */
11176
11177         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
11178
11179         if (cache == NULL) {
11180                 printf("memcache_init failed\n");
11181                 return false;
11182         }
11183
11184         d1 = data_blob_const("d1", 2);
11185         d3 = data_blob_const("d3", 2);
11186
11187         k1 = data_blob_const("d1", 2);
11188         k2 = data_blob_const("d2", 2);
11189         k3 = data_blob_const("d3", 2);
11190
11191         memcache_add(cache, STAT_CACHE, k1, d1);
11192
11193         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
11194                 printf("could not find k1\n");
11195                 return false;
11196         }
11197         if (!data_blob_equal(d1, v1)) {
11198                 return false;
11199         }
11200
11201         memcache_add(cache, STAT_CACHE, k1, d3);
11202
11203         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
11204                 printf("could not find replaced k1\n");
11205                 return false;
11206         }
11207         if (!data_blob_equal(d3, v3)) {
11208                 return false;
11209         }
11210
11211         TALLOC_FREE(cache);
11212
11213         /* GETWD_CACHE TESTS */
11214         str1 = talloc_strdup(mem_ctx, "string1");
11215         if (str1 == NULL) {
11216                 return false;
11217         }
11218         ptr2 = str1; /* Keep an alias for comparison. */
11219
11220         str2 = talloc_strdup(mem_ctx, "string2");
11221         if (str2 == NULL) {
11222                 return false;
11223         }
11224
11225         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
11226         if (cache == NULL) {
11227                 printf("memcache_init failed\n");
11228                 return false;
11229         }
11230
11231         memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
11232         /* str1 == NULL now. */
11233         ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
11234         if (ptr1 == NULL) {
11235                 printf("could not find k2\n");
11236                 return false;
11237         }
11238         if (ptr1 != ptr2) {
11239                 printf("fetch of k2 got wrong string\n");
11240                 return false;
11241         }
11242
11243         /* Add a blob to ensure k2 gets purged. */
11244         d3 = data_blob_talloc_zero(mem_ctx, 180);
11245         memcache_add(cache, STAT_CACHE, k3, d3);
11246
11247         ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
11248         if (ptr2 != NULL) {
11249                 printf("Did find k2, should have been purged\n");
11250                 return false;
11251         }
11252
11253         TALLOC_FREE(cache);
11254         TALLOC_FREE(mem_ctx);
11255
11256         mem_ctx = talloc_init("foo");
11257         if (mem_ctx == NULL) {
11258                 return false;
11259         }
11260
11261         cache = memcache_init(NULL, 0);
11262         if (cache == NULL) {
11263                 return false;
11264         }
11265
11266         str1 = talloc_strdup(mem_ctx, "string1");
11267         if (str1 == NULL) {
11268                 return false;
11269         }
11270         str2 = talloc_strdup(mem_ctx, "string2");
11271         if (str2 == NULL) {
11272                 return false;
11273         }
11274         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
11275                             data_blob_string_const("torture"), &str1);
11276         size1 = talloc_total_size(cache);
11277
11278         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
11279                             data_blob_string_const("torture"), &str2);
11280         size2 = talloc_total_size(cache);
11281
11282         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
11283
11284         if (size2 > size1) {
11285                 printf("memcache leaks memory!\n");
11286                 goto fail;
11287         }
11288
11289         ret = true;
11290  fail:
11291         TALLOC_FREE(cache);
11292         return ret;
11293 }
11294
11295 static void wbclient_done(struct tevent_req *req)
11296 {
11297         wbcErr wbc_err;
11298         struct winbindd_response *wb_resp;
11299         int *i = (int *)tevent_req_callback_data_void(req);
11300
11301         wbc_err = wb_trans_recv(req, req, &wb_resp);
11302         TALLOC_FREE(req);
11303         *i += 1;
11304         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
11305 }
11306
11307 static bool run_wbclient_multi_ping(int dummy)
11308 {
11309         struct tevent_context *ev;
11310         struct wb_context **wb_ctx;
11311         struct winbindd_request wb_req;
11312         bool result = false;
11313         int i, j;
11314
11315         BlockSignals(True, SIGPIPE);
11316
11317         ev = tevent_context_init(talloc_tos());
11318         if (ev == NULL) {
11319                 goto fail;
11320         }
11321
11322         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
11323         if (wb_ctx == NULL) {
11324                 goto fail;
11325         }
11326
11327         ZERO_STRUCT(wb_req);
11328         wb_req.cmd = WINBINDD_PING;
11329
11330         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
11331
11332         for (i=0; i<torture_nprocs; i++) {
11333                 wb_ctx[i] = wb_context_init(ev, NULL);
11334                 if (wb_ctx[i] == NULL) {
11335                         goto fail;
11336                 }
11337                 for (j=0; j<torture_numops; j++) {
11338                         struct tevent_req *req;
11339                         req = wb_trans_send(ev, ev, wb_ctx[i],
11340                                             (j % 2) == 0, &wb_req);
11341                         if (req == NULL) {
11342                                 goto fail;
11343                         }
11344                         tevent_req_set_callback(req, wbclient_done, &i);
11345                 }
11346         }
11347
11348         i = 0;
11349
11350         while (i < torture_nprocs * torture_numops) {
11351                 tevent_loop_once(ev);
11352         }
11353
11354         result = true;
11355  fail:
11356         TALLOC_FREE(ev);
11357         return result;
11358 }
11359
11360 static bool dbtrans_inc(struct db_context *db)
11361 {
11362         struct db_record *rec;
11363         uint32_t val;
11364         bool ret = false;
11365         NTSTATUS status;
11366         TDB_DATA value;
11367
11368         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11369         if (rec == NULL) {
11370                 printf(__location__ "fetch_lock failed\n");
11371                 return false;
11372         }
11373
11374         value = dbwrap_record_get_value(rec);
11375
11376         if (value.dsize != sizeof(uint32_t)) {
11377                 printf(__location__ "value.dsize = %d\n",
11378                        (int)value.dsize);
11379                 goto fail;
11380         }
11381
11382         memcpy(&val, value.dptr, sizeof(val));
11383         val += 1;
11384
11385         status = dbwrap_record_store(
11386                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
11387         if (!NT_STATUS_IS_OK(status)) {
11388                 printf(__location__ "store failed: %s\n",
11389                        nt_errstr(status));
11390                 goto fail;
11391         }
11392
11393         ret = true;
11394 fail:
11395         TALLOC_FREE(rec);
11396         return ret;
11397 }
11398
11399 static bool run_local_dbtrans(int dummy)
11400 {
11401         struct db_context *db;
11402         struct db_record *rec;
11403         NTSTATUS status;
11404         uint32_t initial;
11405         int res;
11406         TDB_DATA value;
11407
11408         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
11409                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
11410                      DBWRAP_FLAG_NONE);
11411         if (db == NULL) {
11412                 printf("Could not open transtest.db\n");
11413                 return false;
11414         }
11415
11416         res = dbwrap_transaction_start(db);
11417         if (res != 0) {
11418                 printf(__location__ "transaction_start failed\n");
11419                 return false;
11420         }
11421
11422         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
11423         if (rec == NULL) {
11424                 printf(__location__ "fetch_lock failed\n");
11425                 return false;
11426         }
11427
11428         value = dbwrap_record_get_value(rec);
11429
11430         if (value.dptr == NULL) {
11431                 initial = 0;
11432                 status = dbwrap_record_store(
11433                         rec, make_tdb_data((uint8_t *)&initial,
11434                                            sizeof(initial)),
11435                         0);
11436                 if (!NT_STATUS_IS_OK(status)) {
11437                         printf(__location__ "store returned %s\n",
11438                                nt_errstr(status));
11439                         return false;
11440                 }
11441         }
11442
11443         TALLOC_FREE(rec);
11444
11445         res = dbwrap_transaction_commit(db);
11446         if (res != 0) {
11447                 printf(__location__ "transaction_commit failed\n");
11448                 return false;
11449         }
11450
11451         while (true) {
11452                 uint32_t val, val2;
11453                 int i;
11454
11455                 res = dbwrap_transaction_start(db);
11456                 if (res != 0) {
11457                         printf(__location__ "transaction_start failed\n");
11458                         break;
11459                 }
11460
11461                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
11462                 if (!NT_STATUS_IS_OK(status)) {
11463                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11464                                nt_errstr(status));
11465                         break;
11466                 }
11467
11468                 for (i=0; i<10; i++) {
11469                         if (!dbtrans_inc(db)) {
11470                                 return false;
11471                         }
11472                 }
11473
11474                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
11475                 if (!NT_STATUS_IS_OK(status)) {
11476                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
11477                                nt_errstr(status));
11478                         break;
11479                 }
11480
11481                 if (val2 != val + 10) {
11482                         printf(__location__ "val=%d, val2=%d\n",
11483                                (int)val, (int)val2);
11484                         break;
11485                 }
11486
11487                 printf("val2=%d\r", val2);
11488
11489                 res = dbwrap_transaction_commit(db);
11490                 if (res != 0) {
11491                         printf(__location__ "transaction_commit failed\n");
11492                         break;
11493                 }
11494         }
11495
11496         TALLOC_FREE(db);
11497         return true;
11498 }
11499
11500 /*
11501  * Just a dummy test to be run under a debugger. There's no real way
11502  * to inspect the tevent_poll specific function from outside of
11503  * tevent_poll.c.
11504  */
11505
11506 static bool run_local_tevent_poll(int dummy)
11507 {
11508         struct tevent_context *ev;
11509         struct tevent_fd *fd1, *fd2;
11510         bool result = false;
11511
11512         ev = tevent_context_init_byname(NULL, "poll");
11513         if (ev == NULL) {
11514                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
11515                 goto fail;
11516         }
11517
11518         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
11519         if (fd1 == NULL) {
11520                 d_fprintf(stderr, "tevent_add_fd failed\n");
11521                 goto fail;
11522         }
11523         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
11524         if (fd2 == NULL) {
11525                 d_fprintf(stderr, "tevent_add_fd failed\n");
11526                 goto fail;
11527         }
11528         TALLOC_FREE(fd2);
11529
11530         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
11531         if (fd2 == NULL) {
11532                 d_fprintf(stderr, "tevent_add_fd failed\n");
11533                 goto fail;
11534         }
11535
11536         result = true;
11537 fail:
11538         TALLOC_FREE(ev);
11539         return result;
11540 }
11541
11542 static bool run_local_hex_encode_buf(int dummy)
11543 {
11544         char buf[17];
11545         uint8_t src[8];
11546         int i;
11547
11548         for (i=0; i<sizeof(src); i++) {
11549                 src[i] = i;
11550         }
11551         hex_encode_buf(buf, src, sizeof(src));
11552         if (strcmp(buf, "0001020304050607") != 0) {
11553                 return false;
11554         }
11555         hex_encode_buf(buf, NULL, 0);
11556         if (buf[0] != '\0') {
11557                 return false;
11558         }
11559         return true;
11560 }
11561
11562 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
11563         "0.0.0.0",
11564         "::0",
11565         "1.2.3.1",
11566         "0.0.0.0",
11567         "0.0.0.0",
11568         "1.2.3.2",
11569         "1.2.3.3",
11570         "1.2.3.4",
11571         "1.2.3.5",
11572         "::0",
11573         "1.2.3.6",
11574         "1.2.3.7",
11575         "::0",
11576         "::0",
11577         "::0",
11578         "1.2.3.8",
11579         "1.2.3.9",
11580         "1.2.3.10",
11581         "1.2.3.11",
11582         "1.2.3.12",
11583         "1.2.3.13",
11584         "1001:1111:1111:1000:0:1111:1111:1111",
11585         "1.2.3.1",
11586         "1.2.3.2",
11587         "1.2.3.3",
11588         "1.2.3.12",
11589         "::0",
11590         "::0"
11591 };
11592
11593 static const char *remove_duplicate_addrs2_test_strings_result[] = {
11594         "1.2.3.1",
11595         "1.2.3.2",
11596         "1.2.3.3",
11597         "1.2.3.4",
11598         "1.2.3.5",
11599         "1.2.3.6",
11600         "1.2.3.7",
11601         "1.2.3.8",
11602         "1.2.3.9",
11603         "1.2.3.10",
11604         "1.2.3.11",
11605         "1.2.3.12",
11606         "1.2.3.13",
11607         "1001:1111:1111:1000:0:1111:1111:1111"
11608 };
11609
11610 static bool run_local_remove_duplicate_addrs2(int dummy)
11611 {
11612         struct ip_service test_vector[28];
11613         int count, i;
11614
11615         /* Construct the sockaddr_storage test vector. */
11616         for (i = 0; i < 28; i++) {
11617                 struct addrinfo hints;
11618                 struct addrinfo *res = NULL;
11619                 int ret;
11620
11621                 memset(&hints, '\0', sizeof(hints));
11622                 hints.ai_flags = AI_NUMERICHOST;
11623                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
11624                                 NULL,
11625                                 &hints,
11626                                 &res);
11627                 if (ret) {
11628                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
11629                                 remove_duplicate_addrs2_test_strings_vector[i]);
11630                         return false;
11631                 }
11632                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
11633                 memcpy(&test_vector[i].ss,
11634                         res->ai_addr,
11635                         res->ai_addrlen);
11636                 freeaddrinfo(res);
11637         }
11638
11639         count = remove_duplicate_addrs2(test_vector, i);
11640
11641         if (count != 14) {
11642                 fprintf(stderr, "count wrong (%d) should be 14\n",
11643                         count);
11644                 return false;
11645         }
11646
11647         for (i = 0; i < count; i++) {
11648                 char addr[INET6_ADDRSTRLEN];
11649
11650                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
11651
11652                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
11653                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
11654                                 i,
11655                                 addr,
11656                                 remove_duplicate_addrs2_test_strings_result[i]);
11657                         return false;
11658                 }
11659         }
11660
11661         printf("run_local_remove_duplicate_addrs2: success\n");
11662         return true;
11663 }
11664
11665 static bool run_local_tdb_opener(int dummy)
11666 {
11667         TDB_CONTEXT *t;
11668         unsigned v = 0;
11669
11670         while (1) {
11671                 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
11672                              O_RDWR|O_CREAT, 0755);
11673                 if (t == NULL) {
11674                         perror("tdb_open failed");
11675                         return false;
11676                 }
11677                 tdb_close(t);
11678
11679                 v += 1;
11680                 printf("\r%u", v);
11681         }
11682         return true;
11683 }
11684
11685 static bool run_local_tdb_writer(int dummy)
11686 {
11687         TDB_CONTEXT *t;
11688         unsigned v = 0;
11689         TDB_DATA val;
11690
11691         t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
11692         if (t == 0) {
11693                 perror("tdb_open failed");
11694                 return 1;
11695         }
11696
11697         val.dptr = (uint8_t *)&v;
11698         val.dsize = sizeof(v);
11699
11700         while (1) {
11701                 TDB_DATA data;
11702                 int ret;
11703
11704                 ret = tdb_store(t, val, val, 0);
11705                 if (ret != 0) {
11706                         printf("%s\n", tdb_errorstr(t));
11707                 }
11708                 v += 1;
11709                 printf("\r%u", v);
11710
11711                 data = tdb_fetch(t, val);
11712                 if (data.dptr != NULL) {
11713                         SAFE_FREE(data.dptr);
11714                 }
11715         }
11716         return true;
11717 }
11718
11719 static bool run_local_canonicalize_path(int dummy)
11720 {
11721         const char *src[] = {
11722                         "/foo/..",
11723                         "/..",
11724                         "/foo/bar/../baz",
11725                         "/foo/././",
11726                         "/../foo",
11727                         ".././././",
11728                         ".././././../../../boo",
11729                         "./..",
11730                         NULL
11731                         };
11732         const char *dst[] = {
11733                         "/",
11734                         "/",
11735                         "/foo/baz",
11736                         "/foo",
11737                         "/foo",
11738                         "/",
11739                         "/boo",
11740                         "/",
11741                         NULL
11742                         };
11743         unsigned int i;
11744
11745         for (i = 0; src[i] != NULL; i++) {
11746                 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
11747                 if (d == NULL) {
11748                         perror("talloc fail\n");
11749                         return false;
11750                 }
11751                 if (strcmp(d, dst[i]) != 0) {
11752                         d_fprintf(stderr,
11753                                 "canonicalize mismatch %s -> %s != %s",
11754                                 src[i], d, dst[i]);
11755                         return false;
11756                 }
11757                 talloc_free(d);
11758         }
11759         return true;
11760 }
11761
11762 static bool run_ign_bad_negprot(int dummy)
11763 {
11764         struct tevent_context *ev;
11765         struct tevent_req *req;
11766         struct smbXcli_conn *conn;
11767         struct sockaddr_storage ss;
11768         NTSTATUS status;
11769         int fd;
11770         bool ok;
11771
11772         printf("starting ignore bad negprot\n");
11773
11774         ok = resolve_name(host, &ss, 0x20, true);
11775         if (!ok) {
11776                 d_fprintf(stderr, "Could not resolve name %s\n", host);
11777                 return false;
11778         }
11779
11780         status = open_socket_out(&ss, 445, 10000, &fd);
11781         if (!NT_STATUS_IS_OK(status)) {
11782                 d_fprintf(stderr, "open_socket_out failed: %s\n",
11783                           nt_errstr(status));
11784                 return false;
11785         }
11786
11787         conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
11788                                    NULL, 0);
11789         if (conn == NULL) {
11790                 d_fprintf(stderr, "smbXcli_conn_create failed\n");
11791                 return false;
11792         }
11793
11794         status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
11795         if (NT_STATUS_IS_OK(status)) {
11796                 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
11797                 return false;
11798         }
11799
11800         ev = samba_tevent_context_init(talloc_tos());
11801         if (ev == NULL) {
11802                 d_fprintf(stderr, "samba_tevent_context_init failed\n");
11803                 return false;
11804         }
11805
11806         req = smb1cli_session_setup_nt1_send(
11807                 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
11808                 data_blob_null, data_blob_null, 0x40,
11809                 "Windows 2000 2195", "Windows 2000 5.0");
11810         if (req == NULL) {
11811                 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
11812                 return false;
11813         }
11814
11815         ok = tevent_req_poll_ntstatus(req, ev, &status);
11816         if (!ok) {
11817                 d_fprintf(stderr, "tevent_req_poll failed\n");
11818                 return false;
11819         }
11820
11821         status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
11822                                                 NULL, NULL);
11823         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
11824                 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
11825                           "%s, expected NT_STATUS_CONNECTION_RESET\n",
11826                           nt_errstr(status));
11827                 return false;
11828         }
11829
11830         TALLOC_FREE(conn);
11831
11832         printf("starting ignore bad negprot\n");
11833
11834         return true;
11835 }
11836
11837 static double create_procs(bool (*fn)(int), bool *result)
11838 {
11839         int i, status;
11840         volatile pid_t *child_status;
11841         volatile bool *child_status_out;
11842         int synccount;
11843         int tries = 8;
11844         struct timeval start;
11845
11846         synccount = 0;
11847
11848         child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
11849         if (!child_status) {
11850                 printf("Failed to setup shared memory\n");
11851                 return -1;
11852         }
11853
11854         child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
11855         if (!child_status_out) {
11856                 printf("Failed to setup result status shared memory\n");
11857                 return -1;
11858         }
11859
11860         for (i = 0; i < torture_nprocs; i++) {
11861                 child_status[i] = 0;
11862                 child_status_out[i] = True;
11863         }
11864
11865         start = timeval_current();
11866
11867         for (i=0;i<torture_nprocs;i++) {
11868                 procnum = i;
11869                 if (fork() == 0) {
11870                         pid_t mypid = getpid();
11871                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
11872
11873                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
11874
11875                         while (1) {
11876                                 if (torture_open_connection(&current_cli, i)) break;
11877                                 if (tries-- == 0) {
11878                                         printf("pid %d failed to start\n", (int)getpid());
11879                                         _exit(1);
11880                                 }
11881                                 smb_msleep(10); 
11882                         }
11883
11884                         child_status[i] = getpid();
11885
11886                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
11887
11888                         child_status_out[i] = fn(i);
11889                         _exit(0);
11890                 }
11891         }
11892
11893         do {
11894                 synccount = 0;
11895                 for (i=0;i<torture_nprocs;i++) {
11896                         if (child_status[i]) synccount++;
11897                 }
11898                 if (synccount == torture_nprocs) break;
11899                 smb_msleep(10);
11900         } while (timeval_elapsed(&start) < 30);
11901
11902         if (synccount != torture_nprocs) {
11903                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
11904                 *result = False;
11905                 return timeval_elapsed(&start);
11906         }
11907
11908         /* start the client load */
11909         start = timeval_current();
11910
11911         for (i=0;i<torture_nprocs;i++) {
11912                 child_status[i] = 0;
11913         }
11914
11915         printf("%d clients started\n", torture_nprocs);
11916
11917         for (i=0;i<torture_nprocs;i++) {
11918                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
11919         }
11920
11921         printf("\n");
11922
11923         for (i=0;i<torture_nprocs;i++) {
11924                 if (!child_status_out[i]) {
11925                         *result = False;
11926                 }
11927         }
11928         return timeval_elapsed(&start);
11929 }
11930
11931 #define FLAG_MULTIPROC 1
11932
11933 static struct {
11934         const char *name;
11935         bool (*fn)(int);
11936         unsigned flags;
11937 } torture_ops[] = {
11938         {
11939                 .name = "FDPASS",
11940                 .fn   = run_fdpasstest,
11941         },
11942         {
11943                 .name = "LOCK1",
11944                 .fn   = run_locktest1,
11945         },
11946         {
11947                 .name = "LOCK2",
11948                 .fn   =  run_locktest2,
11949         },
11950         {
11951                 .name = "LOCK3",
11952                 .fn   =  run_locktest3,
11953         },
11954         {
11955                 .name = "LOCK4",
11956                 .fn   =  run_locktest4,
11957         },
11958         {
11959                 .name = "LOCK5",
11960                 .fn   =  run_locktest5,
11961         },
11962         {
11963                 .name = "LOCK6",
11964                 .fn   =  run_locktest6,
11965         },
11966         {
11967                 .name = "LOCK7",
11968                 .fn   =  run_locktest7,
11969         },
11970         {
11971                 .name = "LOCK8",
11972                 .fn   =  run_locktest8,
11973         },
11974         {
11975                 .name = "LOCK9",
11976                 .fn   =  run_locktest9,
11977         },
11978         {
11979                 .name = "UNLINK",
11980                 .fn   = run_unlinktest,
11981         },
11982         {
11983                 .name = "BROWSE",
11984                 .fn   = run_browsetest,
11985         },
11986         {
11987                 .name = "ATTR",
11988                 .fn   =   run_attrtest,
11989         },
11990         {
11991                 .name = "TRANS2",
11992                 .fn   = run_trans2test,
11993         },
11994         {
11995                 .name  = "MAXFID",
11996                 .fn    = run_maxfidtest,
11997                 .flags = FLAG_MULTIPROC,
11998         },
11999         {
12000                 .name  = "TORTURE",
12001                 .fn    = run_torture,
12002                 .flags = FLAG_MULTIPROC,
12003         },
12004         {
12005                 .name  = "RANDOMIPC",
12006                 .fn    = run_randomipc,
12007         },
12008         {
12009                 .name  = "NEGNOWAIT",
12010                 .fn    = run_negprot_nowait,
12011         },
12012         {
12013                 .name  = "NBENCH",
12014                 .fn    =  run_nbench,
12015         },
12016         {
12017                 .name  = "NBENCH2",
12018                 .fn    = run_nbench2,
12019         },
12020         {
12021                 .name  = "OPLOCK1",
12022                 .fn    =  run_oplock1,
12023         },
12024         {
12025                 .name  = "OPLOCK2",
12026                 .fn    =  run_oplock2,
12027         },
12028         {
12029                 .name  = "OPLOCK4",
12030                 .fn    =  run_oplock4,
12031         },
12032         {
12033                 .name  = "DIR",
12034                 .fn    =  run_dirtest,
12035         },
12036         {
12037                 .name  = "DIR1",
12038                 .fn    =  run_dirtest1,
12039         },
12040         {
12041                 .name  = "DIR-CREATETIME",
12042                 .fn    =  run_dir_createtime,
12043         },
12044         {
12045                 .name  = "DENY1",
12046                 .fn    =  torture_denytest1,
12047         },
12048         {
12049                 .name  = "DENY2",
12050                 .fn    =  torture_denytest2,
12051         },
12052         {
12053                 .name  = "TCON",
12054                 .fn    =  run_tcon_test,
12055         },
12056         {
12057                 .name  = "TCONDEV",
12058                 .fn    =  run_tcon_devtype_test,
12059         },
12060         {
12061                 .name  = "RW1",
12062                 .fn    =  run_readwritetest,
12063         },
12064         {
12065                 .name  = "RW2",
12066                 .fn    =  run_readwritemulti,
12067                 .flags = FLAG_MULTIPROC
12068         },
12069         {
12070                 .name  = "RW3",
12071                 .fn    =  run_readwritelarge,
12072         },
12073         {
12074                 .name  = "RW-SIGNING",
12075                 .fn    =  run_readwritelarge_signtest,
12076         },
12077         {
12078                 .name  = "OPEN",
12079                 .fn    = run_opentest,
12080         },
12081         {
12082                 .name  = "POSIX",
12083                 .fn    = run_simple_posix_open_test,
12084         },
12085         {
12086                 .name  = "POSIX-APPEND",
12087                 .fn    = run_posix_append,
12088         },
12089         {
12090                 .name  = "POSIX-SYMLINK-ACL",
12091                 .fn    = run_acl_symlink_test,
12092         },
12093         {
12094                 .name  = "POSIX-SYMLINK-EA",
12095                 .fn    = run_ea_symlink_test,
12096         },
12097         {
12098                 .name  = "POSIX-STREAM-DELETE",
12099                 .fn    = run_posix_stream_delete,
12100         },
12101         {
12102                 .name  = "POSIX-OFD-LOCK",
12103                 .fn    = run_posix_ofd_lock_test,
12104         },
12105         {
12106                 .name  = "POSIX-MKDIR",
12107                 .fn    = run_posix_mkdir_test,
12108         },
12109         {
12110                 .name  = "WINDOWS-BAD-SYMLINK",
12111                 .fn    = run_symlink_open_test,
12112         },
12113         {
12114                 .name  = "CASE-INSENSITIVE-CREATE",
12115                 .fn    = run_case_insensitive_create,
12116         },
12117         {
12118                 .name  = "ASYNC-ECHO",
12119                 .fn    = run_async_echo,
12120         },
12121         {
12122                 .name  = "UID-REGRESSION-TEST",
12123                 .fn    = run_uid_regression_test,
12124         },
12125         {
12126                 .name  = "SHORTNAME-TEST",
12127                 .fn    = run_shortname_test,
12128         },
12129         {
12130                 .name  = "ADDRCHANGE",
12131                 .fn    = run_addrchange,
12132         },
12133 #if 1
12134         {
12135                 .name  = "OPENATTR",
12136                 .fn    = run_openattrtest,
12137         },
12138 #endif
12139         {
12140                 .name  = "XCOPY",
12141                 .fn    = run_xcopy,
12142         },
12143         {
12144                 .name  = "RENAME",
12145                 .fn    = run_rename,
12146         },
12147         {
12148                 .name  = "RENAME-ACCESS",
12149                 .fn    = run_rename_access,
12150         },
12151         {
12152                 .name  = "OWNER-RIGHTS",
12153                 .fn    = run_owner_rights,
12154         },
12155         {
12156                 .name  = "DELETE",
12157                 .fn    = run_deletetest,
12158         },
12159         {
12160                 .name  = "DELETE-PRINT",
12161                 .fn    = run_delete_print_test,
12162         },
12163         {
12164                 .name  = "WILDDELETE",
12165                 .fn    = run_wild_deletetest,
12166         },
12167         {
12168                 .name  = "DELETE-LN",
12169                 .fn    = run_deletetest_ln,
12170         },
12171         {
12172                 .name  = "PROPERTIES",
12173                 .fn    = run_properties,
12174         },
12175         {
12176                 .name  = "MANGLE",
12177                 .fn    = torture_mangle,
12178         },
12179         {
12180                 .name  = "MANGLE1",
12181                 .fn    = run_mangle1,
12182         },
12183         {
12184                 .name  = "MANGLE-ILLEGAL",
12185                 .fn    = run_mangle_illegal,
12186         },
12187         {
12188                 .name  = "W2K",
12189                 .fn    = run_w2ktest,
12190         },
12191         {
12192                 .name  = "TRANS2SCAN",
12193                 .fn    = torture_trans2_scan,
12194         },
12195         {
12196                 .name  = "NTTRANSSCAN",
12197                 .fn    = torture_nttrans_scan,
12198         },
12199         {
12200                 .name  = "UTABLE",
12201                 .fn    = torture_utable,
12202         },
12203         {
12204                 .name  = "CASETABLE",
12205                 .fn    = torture_casetable,
12206         },
12207         {
12208                 .name  = "ERRMAPEXTRACT",
12209                 .fn    = run_error_map_extract,
12210         },
12211         {
12212                 .name  = "PIPE_NUMBER",
12213                 .fn    = run_pipe_number,
12214         },
12215         {
12216                 .name  = "TCON2",
12217                 .fn    =  run_tcon2_test,
12218         },
12219         {
12220                 .name  = "IOCTL",
12221                 .fn    =  torture_ioctl_test,
12222         },
12223         {
12224                 .name  = "CHKPATH",
12225                 .fn    =  torture_chkpath_test,
12226         },
12227         {
12228                 .name  = "FDSESS",
12229                 .fn    = run_fdsesstest,
12230         },
12231         {
12232                 .name  = "EATEST",
12233                 .fn    = run_eatest,
12234         },
12235         {
12236                 .name  = "SESSSETUP_BENCH",
12237                 .fn    = run_sesssetup_bench,
12238         },
12239         {
12240                 .name  = "CHAIN1",
12241                 .fn    = run_chain1,
12242         },
12243         {
12244                 .name  = "CHAIN2",
12245                 .fn    = run_chain2,
12246         },
12247         {
12248                 .name  = "CHAIN3",
12249                 .fn    = run_chain3,
12250         },
12251         {
12252                 .name  = "WINDOWS-WRITE",
12253                 .fn    = run_windows_write,
12254         },
12255         {
12256                 .name  = "LARGE_READX",
12257                 .fn    = run_large_readx,
12258         },
12259         {
12260                 .name  = "NTTRANS-CREATE",
12261                 .fn    = run_nttrans_create,
12262         },
12263         {
12264                 .name  = "NTTRANS-FSCTL",
12265                 .fn    = run_nttrans_fsctl,
12266         },
12267         {
12268                 .name  = "CLI_ECHO",
12269                 .fn    = run_cli_echo,
12270         },
12271         {
12272                 .name  = "CLI_SPLICE",
12273                 .fn    = run_cli_splice,
12274         },
12275         {
12276                 .name  = "TLDAP",
12277                 .fn    = run_tldap,
12278         },
12279         {
12280                 .name  = "STREAMERROR",
12281                 .fn    = run_streamerror,
12282         },
12283         {
12284                 .name  = "NOTIFY-BENCH",
12285                 .fn    = run_notify_bench,
12286         },
12287         {
12288                 .name  = "NOTIFY-BENCH2",
12289                 .fn    = run_notify_bench2,
12290         },
12291         {
12292                 .name  = "NOTIFY-BENCH3",
12293                 .fn    = run_notify_bench3,
12294         },
12295         {
12296                 .name  = "BAD-NBT-SESSION",
12297                 .fn    = run_bad_nbt_session,
12298         },
12299         {
12300                 .name  = "IGN-BAD-NEGPROT",
12301                 .fn    = run_ign_bad_negprot,
12302         },
12303         {
12304                 .name  = "SMB-ANY-CONNECT",
12305                 .fn    = run_smb_any_connect,
12306         },
12307         {
12308                 .name  = "NOTIFY-ONLINE",
12309                 .fn    = run_notify_online,
12310         },
12311         {
12312                 .name  = "SMB2-BASIC",
12313                 .fn    = run_smb2_basic,
12314         },
12315         {
12316                 .name  = "SMB2-NEGPROT",
12317                 .fn    = run_smb2_negprot,
12318         },
12319         {
12320                 .name  = "SMB2-ANONYMOUS",
12321                 .fn    = run_smb2_anonymous,
12322         },
12323         {
12324                 .name  = "SMB2-SESSION-RECONNECT",
12325                 .fn    = run_smb2_session_reconnect,
12326         },
12327         {
12328                 .name  = "SMB2-TCON-DEPENDENCE",
12329                 .fn    = run_smb2_tcon_dependence,
12330         },
12331         {
12332                 .name  = "SMB2-MULTI-CHANNEL",
12333                 .fn    = run_smb2_multi_channel,
12334         },
12335         {
12336                 .name  = "SMB2-SESSION-REAUTH",
12337                 .fn    = run_smb2_session_reauth,
12338         },
12339         {
12340                 .name  = "SMB2-FTRUNCATE",
12341                 .fn    = run_smb2_ftruncate,
12342         },
12343         {
12344                 .name  = "SMB2-DIR-FSYNC",
12345                 .fn    = run_smb2_dir_fsync,
12346         },
12347         {
12348                 .name  = "CLEANUP1",
12349                 .fn    = run_cleanup1,
12350         },
12351         {
12352                 .name  = "CLEANUP2",
12353                 .fn    = run_cleanup2,
12354         },
12355         {
12356                 .name  = "CLEANUP3",
12357                 .fn    = run_cleanup3,
12358         },
12359         {
12360                 .name  = "CLEANUP4",
12361                 .fn    = run_cleanup4,
12362         },
12363         {
12364                 .name  = "OPLOCK-CANCEL",
12365                 .fn    = run_oplock_cancel,
12366         },
12367         {
12368                 .name  = "PIDHIGH",
12369                 .fn    = run_pidhigh,
12370         },
12371         {
12372                 .name  = "LOCAL-SUBSTITUTE",
12373                 .fn    = run_local_substitute,
12374         },
12375         {
12376                 .name  = "LOCAL-GENCACHE",
12377                 .fn    = run_local_gencache,
12378         },
12379         {
12380                 .name  = "LOCAL-DBWRAP-WATCH1",
12381                 .fn    = run_dbwrap_watch1,
12382         },
12383         {
12384                 .name  = "LOCAL-DBWRAP-WATCH2",
12385                 .fn    = run_dbwrap_watch2,
12386         },
12387         {
12388                 .name  = "LOCAL-DBWRAP-DO-LOCKED1",
12389                 .fn    = run_dbwrap_do_locked1,
12390         },
12391         {
12392                 .name  = "LOCAL-MESSAGING-READ1",
12393                 .fn    = run_messaging_read1,
12394         },
12395         {
12396                 .name  = "LOCAL-MESSAGING-READ2",
12397                 .fn    = run_messaging_read2,
12398         },
12399         {
12400                 .name  = "LOCAL-MESSAGING-READ3",
12401                 .fn    = run_messaging_read3,
12402         },
12403         {
12404                 .name  = "LOCAL-MESSAGING-READ4",
12405                 .fn    = run_messaging_read4,
12406         },
12407         {
12408                 .name  = "LOCAL-MESSAGING-FDPASS1",
12409                 .fn    = run_messaging_fdpass1,
12410         },
12411         {
12412                 .name  = "LOCAL-MESSAGING-FDPASS2",
12413                 .fn    = run_messaging_fdpass2,
12414         },
12415         {
12416                 .name  = "LOCAL-MESSAGING-FDPASS2a",
12417                 .fn    = run_messaging_fdpass2a,
12418         },
12419         {
12420                 .name  = "LOCAL-MESSAGING-FDPASS2b",
12421                 .fn    = run_messaging_fdpass2b,
12422         },
12423         {
12424                 .name  = "LOCAL-MESSAGING-SEND-ALL",
12425                 .fn    = run_messaging_send_all,
12426         },
12427         {
12428                 .name  = "LOCAL-BASE64",
12429                 .fn    = run_local_base64,
12430         },
12431         {
12432                 .name  = "LOCAL-RBTREE",
12433                 .fn    = run_local_rbtree,
12434         },
12435         {
12436                 .name  = "LOCAL-MEMCACHE",
12437                 .fn    = run_local_memcache,
12438         },
12439         {
12440                 .name  = "LOCAL-STREAM-NAME",
12441                 .fn    = run_local_stream_name,
12442         },
12443         {
12444                 .name  = "WBCLIENT-MULTI-PING",
12445                 .fn    = run_wbclient_multi_ping,
12446         },
12447         {
12448                 .name  = "LOCAL-string_to_sid",
12449                 .fn    = run_local_string_to_sid,
12450         },
12451         {
12452                 .name  = "LOCAL-sid_to_string",
12453                 .fn    = run_local_sid_to_string,
12454         },
12455         {
12456                 .name  = "LOCAL-binary_to_sid",
12457                 .fn    = run_local_binary_to_sid,
12458         },
12459         {
12460                 .name  = "LOCAL-DBTRANS",
12461                 .fn    = run_local_dbtrans,
12462         },
12463         {
12464                 .name  = "LOCAL-TEVENT-POLL",
12465                 .fn    = run_local_tevent_poll,
12466         },
12467         {
12468                 .name  = "LOCAL-CONVERT-STRING",
12469                 .fn    = run_local_convert_string,
12470         },
12471         {
12472                 .name  = "LOCAL-CONV-AUTH-INFO",
12473                 .fn    = run_local_conv_auth_info,
12474         },
12475         {
12476                 .name  = "LOCAL-hex_encode_buf",
12477                 .fn    = run_local_hex_encode_buf,
12478         },
12479         {
12480                 .name  = "LOCAL-IDMAP-TDB-COMMON",
12481                 .fn    = run_idmap_tdb_common_test,
12482         },
12483         {
12484                 .name  = "LOCAL-remove_duplicate_addrs2",
12485                 .fn    = run_local_remove_duplicate_addrs2,
12486         },
12487         {
12488                 .name  = "local-tdb-opener",
12489                 .fn    = run_local_tdb_opener,
12490         },
12491         {
12492                 .name  = "local-tdb-writer",
12493                 .fn    = run_local_tdb_writer,
12494         },
12495         {
12496                 .name  = "LOCAL-DBWRAP-CTDB",
12497                 .fn    = run_local_dbwrap_ctdb,
12498         },
12499         {
12500                 .name  = "LOCAL-BENCH-PTHREADPOOL",
12501                 .fn    = run_bench_pthreadpool,
12502         },
12503         {
12504                 .name  = "LOCAL-PTHREADPOOL-TEVENT",
12505                 .fn    = run_pthreadpool_tevent,
12506         },
12507         {
12508                 .name  = "LOCAL-G-LOCK1",
12509                 .fn    = run_g_lock1,
12510         },
12511         {
12512                 .name  = "LOCAL-G-LOCK2",
12513                 .fn    = run_g_lock2,
12514         },
12515         {
12516                 .name  = "LOCAL-G-LOCK3",
12517                 .fn    = run_g_lock3,
12518         },
12519         {
12520                 .name  = "LOCAL-G-LOCK4",
12521                 .fn    = run_g_lock4,
12522         },
12523         {
12524                 .name  = "LOCAL-G-LOCK5",
12525                 .fn    = run_g_lock5,
12526         },
12527         {
12528                 .name  = "LOCAL-G-LOCK6",
12529                 .fn    = run_g_lock6,
12530         },
12531         {
12532                 .name  = "LOCAL-G-LOCK-PING-PONG",
12533                 .fn    = run_g_lock_ping_pong,
12534         },
12535         {
12536                 .name  = "LOCAL-CANONICALIZE-PATH",
12537                 .fn    = run_local_canonicalize_path,
12538         },
12539         {
12540                 .name  = "LOCAL-NAMEMAP-CACHE1",
12541                 .fn    = run_local_namemap_cache1,
12542         },
12543         {
12544                 .name  = "LOCAL-IDMAP-CACHE1",
12545                 .fn    = run_local_idmap_cache1,
12546         },
12547         {
12548                 .name  = "qpathinfo-bufsize",
12549                 .fn    = run_qpathinfo_bufsize,
12550         },
12551         {
12552                 .name  = "hide-new-files-timeout",
12553                 .fn    = run_hidenewfiles,
12554         },
12555         {
12556                 .name = NULL,
12557         },
12558 };
12559
12560 /****************************************************************************
12561 run a specified test or "ALL"
12562 ****************************************************************************/
12563 static bool run_test(const char *name)
12564 {
12565         bool ret = True;
12566         bool result = True;
12567         bool found = False;
12568         int i;
12569         double t;
12570         if (strequal(name,"ALL")) {
12571                 for (i=0;torture_ops[i].name;i++) {
12572                         run_test(torture_ops[i].name);
12573                 }
12574                 found = True;
12575         }
12576
12577         for (i=0;torture_ops[i].name;i++) {
12578                 fstr_sprintf(randomfname, "\\XX%x", 
12579                          (unsigned)random());
12580
12581                 if (strequal(name, torture_ops[i].name)) {
12582                         found = True;
12583                         printf("Running %s\n", name);
12584                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
12585                                 t = create_procs(torture_ops[i].fn, &result);
12586                                 if (!result) { 
12587                                         ret = False;
12588                                         printf("TEST %s FAILED!\n", name);
12589                                 }
12590                         } else {
12591                                 struct timeval start;
12592                                 start = timeval_current();
12593                                 if (!torture_ops[i].fn(0)) {
12594                                         ret = False;
12595                                         printf("TEST %s FAILED!\n", name);
12596                                 }
12597                                 t = timeval_elapsed(&start);
12598                         }
12599                         printf("%s took %g secs\n\n", name, t);
12600                 }
12601         }
12602
12603         if (!found) {
12604                 printf("Did not find a test named %s\n", name);
12605                 ret = False;
12606         }
12607
12608         return ret;
12609 }
12610
12611
12612 static void usage(void)
12613 {
12614         int i;
12615
12616         printf("WARNING samba4 test suite is much more complete nowadays.\n");
12617         printf("Please use samba4 torture.\n\n");
12618
12619         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
12620
12621         printf("\t-d debuglevel\n");
12622         printf("\t-U user%%pass\n");
12623         printf("\t-k                    use kerberos\n");
12624         printf("\t-N numprocs\n");
12625         printf("\t-n my_netbios_name\n");
12626         printf("\t-W workgroup\n");
12627         printf("\t-o num_operations\n");
12628         printf("\t-O socket_options\n");
12629         printf("\t-m maximum protocol\n");
12630         printf("\t-L use oplocks\n");
12631         printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
12632         printf("\t-A showall\n");
12633         printf("\t-p port\n");
12634         printf("\t-s seed\n");
12635         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
12636         printf("\t-f filename           filename to test\n");
12637         printf("\t-e                    encrypt\n");
12638         printf("\n\n");
12639
12640         printf("tests are:");
12641         for (i=0;torture_ops[i].name;i++) {
12642                 printf(" %s", torture_ops[i].name);
12643         }
12644         printf("\n");
12645
12646         printf("default test is ALL\n");
12647
12648         exit(1);
12649 }
12650
12651 /****************************************************************************
12652   main program
12653 ****************************************************************************/
12654  int main(int argc,char *argv[])
12655 {
12656         int opt, i;
12657         char *p;
12658         int gotuser = 0;
12659         int gotpass = 0;
12660         bool correct = True;
12661         TALLOC_CTX *frame = talloc_stackframe();
12662         int seed = time(NULL);
12663
12664 #ifdef HAVE_SETBUFFER
12665         setbuffer(stdout, NULL, 0);
12666 #endif
12667
12668         setup_logging("smbtorture", DEBUG_STDOUT);
12669
12670         smb_init_locale();
12671         fault_setup();
12672
12673         if (is_default_dyn_CONFIGFILE()) {
12674                 if(getenv("SMB_CONF_PATH")) {
12675                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
12676                 }
12677         }
12678         lp_load_global(get_dyn_CONFIGFILE());
12679         load_interfaces();
12680
12681         if (argc < 2) {
12682                 usage();
12683         }
12684
12685         for(p = argv[1]; *p; p++)
12686           if(*p == '\\')
12687             *p = '/';
12688
12689         if (strncmp(argv[1], "//", 2)) {
12690                 usage();
12691         }
12692
12693         fstrcpy(host, &argv[1][2]);
12694         p = strchr_m(&host[2],'/');
12695         if (!p) {
12696                 usage();
12697         }
12698         *p = 0;
12699         fstrcpy(share, p+1);
12700
12701         fstrcpy(myname, get_myname(talloc_tos()));
12702         if (!*myname) {
12703                 fprintf(stderr, "Failed to get my hostname.\n");
12704                 return 1;
12705         }
12706
12707         if (*username == 0 && getenv("LOGNAME")) {
12708           fstrcpy(username,getenv("LOGNAME"));
12709         }
12710
12711         argc--;
12712         argv++;
12713
12714         fstrcpy(workgroup, lp_workgroup());
12715
12716         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
12717                != EOF) {
12718                 switch (opt) {
12719                 case 'p':
12720                         port_to_use = atoi(optarg);
12721                         break;
12722                 case 's':
12723                         seed = atoi(optarg);
12724                         break;
12725                 case 'W':
12726                         fstrcpy(workgroup,optarg);
12727                         break;
12728                 case 'm':
12729                         lp_set_cmdline("client max protocol", optarg);
12730                         break;
12731                 case 'N':
12732                         torture_nprocs = atoi(optarg);
12733                         break;
12734                 case 'o':
12735                         torture_numops = atoi(optarg);
12736                         break;
12737                 case 'd':
12738                         lp_set_cmdline("log level", optarg);
12739                         break;
12740                 case 'O':
12741                         sockops = optarg;
12742                         break;
12743                 case 'L':
12744                         use_oplocks = True;
12745                         break;
12746                 case 'l':
12747                         local_path = optarg;
12748                         break;
12749                 case 'A':
12750                         torture_showall = True;
12751                         break;
12752                 case 'n':
12753                         fstrcpy(myname, optarg);
12754                         break;
12755                 case 'c':
12756                         client_txt = optarg;
12757                         break;
12758                 case 'e':
12759                         do_encrypt = true;
12760                         break;
12761                 case 'k':
12762 #ifdef HAVE_KRB5
12763                         use_kerberos = True;
12764 #else
12765                         d_printf("No kerberos support compiled in\n");
12766                         exit(1);
12767 #endif
12768                         break;
12769                 case 'U':
12770                         gotuser = 1;
12771                         fstrcpy(username,optarg);
12772                         p = strchr_m(username,'%');
12773                         if (p) {
12774                                 *p = 0;
12775                                 fstrcpy(password, p+1);
12776                                 gotpass = 1;
12777                         }
12778                         break;
12779                 case 'b':
12780                         fstrcpy(multishare_conn_fname, optarg);
12781                         use_multishare_conn = True;
12782                         break;
12783                 case 'B':
12784                         torture_blocksize = atoi(optarg);
12785                         break;
12786                 case 'f':
12787                         test_filename = SMB_STRDUP(optarg);
12788                         break;
12789                 default:
12790                         printf("Unknown option %c (%d)\n", (char)opt, opt);
12791                         usage();
12792                 }
12793         }
12794
12795         d_printf("using seed %d\n", seed);
12796
12797         srandom(seed);
12798
12799         if(use_kerberos && !gotuser) gotpass = True;
12800
12801         while (!gotpass) {
12802                 char pwd[256] = {0};
12803                 int rc;
12804
12805                 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
12806                 if (rc == 0) {
12807                         fstrcpy(password, pwd);
12808                         gotpass = 1;
12809                 }
12810         }
12811
12812         printf("host=%s share=%s user=%s myname=%s\n", 
12813                host, share, username, myname);
12814
12815         torture_creds = cli_session_creds_init(frame,
12816                                                username,
12817                                                workgroup,
12818                                                NULL, /* realm */
12819                                                password,
12820                                                use_kerberos,
12821                                                false, /* fallback_after_kerberos */
12822                                                false, /* use_ccache */
12823                                                false); /* password_is_nt_hash */
12824         if (torture_creds == NULL) {
12825                 d_printf("cli_session_creds_init() failed.\n");
12826                 exit(1);
12827         }
12828
12829         if (argc == optind) {
12830                 correct = run_test("ALL");
12831         } else {
12832                 for (i=optind;i<argc;i++) {
12833                         if (!run_test(argv[i])) {
12834                                 correct = False;
12835                         }
12836                 }
12837         }
12838
12839         TALLOC_FREE(frame);
12840
12841         if (correct) {
12842                 return(0);
12843         } else {
12844                 return(1);
12845         }
12846 }